mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-03-30 11:16:35 +00:00
fix: disable callback URLs with protocols "javascript" and "data"
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pocket-id/pocket-id/backend/internal/utils"
|
||||
@@ -19,38 +21,38 @@ var validateUsernameRegex = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9_.@-]*[a-
|
||||
var validateClientIDRegex = regexp.MustCompile("^[a-zA-Z0-9._-]+$")
|
||||
|
||||
func init() {
|
||||
v := binding.Validator.Engine().(*validator.Validate)
|
||||
engine := binding.Validator.Engine().(*validator.Validate)
|
||||
|
||||
// Maximum allowed value for TTLs
|
||||
const maxTTL = 31 * 24 * time.Hour
|
||||
|
||||
if err := v.RegisterValidation("username", func(fl validator.FieldLevel) bool {
|
||||
return ValidateUsername(fl.Field().String())
|
||||
}); err != nil {
|
||||
panic("Failed to register custom validation for username: " + err.Error())
|
||||
validators := map[string]validator.Func{
|
||||
"username": func(fl validator.FieldLevel) bool {
|
||||
return ValidateUsername(fl.Field().String())
|
||||
},
|
||||
"client_id": func(fl validator.FieldLevel) bool {
|
||||
return ValidateClientID(fl.Field().String())
|
||||
},
|
||||
"ttl": func(fl validator.FieldLevel) bool {
|
||||
ttl, ok := fl.Field().Interface().(utils.JSONDuration)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
// Allow zero, which means the field wasn't set
|
||||
return ttl.Duration == 0 || (ttl.Duration > time.Second && ttl.Duration <= maxTTL)
|
||||
},
|
||||
"callback_url": func(fl validator.FieldLevel) bool {
|
||||
return ValidateCallbackURL(fl.Field().String())
|
||||
},
|
||||
"callback_url_pattern": func(fl validator.FieldLevel) bool {
|
||||
return ValidateCallbackURLPattern(fl.Field().String())
|
||||
},
|
||||
}
|
||||
|
||||
if err := v.RegisterValidation("client_id", func(fl validator.FieldLevel) bool {
|
||||
return ValidateClientID(fl.Field().String())
|
||||
}); err != nil {
|
||||
panic("Failed to register custom validation for client_id: " + err.Error())
|
||||
}
|
||||
|
||||
if err := v.RegisterValidation("ttl", func(fl validator.FieldLevel) bool {
|
||||
ttl, ok := fl.Field().Interface().(utils.JSONDuration)
|
||||
if !ok {
|
||||
return false
|
||||
for k, v := range validators {
|
||||
err := engine.RegisterValidation(k, v)
|
||||
if err != nil {
|
||||
panic("Failed to register custom validation for " + k + ": " + err.Error())
|
||||
}
|
||||
// Allow zero, which means the field wasn't set
|
||||
return ttl.Duration == 0 || (ttl.Duration > time.Second && ttl.Duration <= maxTTL)
|
||||
}); err != nil {
|
||||
panic("Failed to register custom validation for ttl: " + err.Error())
|
||||
}
|
||||
|
||||
if err := v.RegisterValidation("callback_url", func(fl validator.FieldLevel) bool {
|
||||
return ValidateCallbackURL(fl.Field().String())
|
||||
}); err != nil {
|
||||
panic("Failed to register custom validation for callback_url: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +66,24 @@ func ValidateClientID(clientID string) bool {
|
||||
return validateClientIDRegex.MatchString(clientID)
|
||||
}
|
||||
|
||||
// ValidateCallbackURL validates callback URLs with support for wildcards
|
||||
func ValidateCallbackURL(raw string) bool {
|
||||
// ValidateCallbackURL validates the input callback URL
|
||||
func ValidateCallbackURL(str string) bool {
|
||||
// Ensure the URL is a valid one and that the protocol is not "javascript:" or "data:"
|
||||
u, err := url.Parse(str)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "javascript", "data":
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateCallbackURLPattern validates callback URL patterns, with support for wildcards
|
||||
func ValidateCallbackURLPattern(raw string) bool {
|
||||
err := utils.ValidateCallbackURLPattern(raw)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user