error
This commit is contained in:
parent
44500afd3f
commit
5d370e1077
13 changed files with 529 additions and 519 deletions
152
api/validator.go
Normal file
152
api/validator.go
Normal file
|
@ -0,0 +1,152 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
// Validate is a global validator instance
|
||||
var Validate = validator.New()
|
||||
|
||||
// RegisterCustomValidations registers custom validation functions
|
||||
func RegisterCustomValidations() {
|
||||
// Register custom validation for issuer
|
||||
Validate.RegisterValidation("issuer", validateIssuer)
|
||||
|
||||
// Register custom validation for XSS prevention
|
||||
Validate.RegisterValidation("no_xss", validateNoXSS)
|
||||
|
||||
// Register custom validation for OTP secret
|
||||
Validate.RegisterValidation("otpsecret", validateOTPSecret)
|
||||
}
|
||||
|
||||
// validateOTPSecret validates that the OTP secret is in valid base32 format
|
||||
func validateOTPSecret(fl validator.FieldLevel) bool {
|
||||
secret := fl.Field().String()
|
||||
|
||||
// Check if the secret is not empty
|
||||
if secret == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the secret is in base32 format (A-Z, 2-7)
|
||||
base32Regex := regexp.MustCompile(`^[A-Z2-7]+=*$`)
|
||||
if !base32Regex.MatchString(secret) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the length is valid (must be at least 16 characters)
|
||||
if len(secret) < 16 || len(secret) > 128 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// validateIssuer validates that the issuer field contains only allowed characters
|
||||
func validateIssuer(fl validator.FieldLevel) bool {
|
||||
issuer := fl.Field().String()
|
||||
|
||||
// Empty issuer is valid (since it's optional)
|
||||
if issuer == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Allow alphanumeric characters, spaces, and common punctuation
|
||||
issuerRegex := regexp.MustCompile(`^[a-zA-Z0-9\s\-_.,:;!?()[\]{}'"]+package api
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
// Validate is a global validator instance
|
||||
var Validate = validator.New()
|
||||
|
||||
// RegisterCustomValidations registers custom validation functions
|
||||
func RegisterCustomValidations() {
|
||||
// Register custom validation for issuer
|
||||
Validate.RegisterValidation("issuer", validateIssuer)
|
||||
|
||||
// Register custom validation for XSS prevention
|
||||
Validate.RegisterValidation("no_xss", validateNoXSS)
|
||||
|
||||
// Register custom validation for OTP secret
|
||||
Validate.RegisterValidation("otpsecret", validateOTPSecret)
|
||||
}
|
||||
|
||||
// validateOTPSecret validates that the OTP secret is in valid base32 format
|
||||
func validateOTPSecret(fl validator.FieldLevel) bool {
|
||||
secret := fl.Field().String()
|
||||
|
||||
// Check if the secret is not empty
|
||||
if secret == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the secret is in base32 format (A-Z, 2-7)
|
||||
base32Regex := regexp.MustCompile(`^[A-Z2-7]+=*$`)
|
||||
if !base32Regex.MatchString(secret) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the length is valid (must be at least 16 characters)
|
||||
if len(secret) < 16 || len(secret) > 128 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
)
|
||||
if !issuerRegex.MatchString(issuer) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check length
|
||||
if len(issuer) > 100 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// validateNoXSS validates that the field doesn't contain potential XSS payloads
|
||||
func validateNoXSS(fl validator.FieldLevel) bool {
|
||||
value := fl.Field().String()
|
||||
|
||||
// Check for HTML encoding
|
||||
if strings.Contains(value, "&#") ||
|
||||
strings.Contains(value, "<") ||
|
||||
strings.Contains(value, ">") {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for common XSS patterns
|
||||
suspiciousPatterns := []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)<script[^>]*>.*?</script>`),
|
||||
regexp.MustCompile(`(?i)javascript:`),
|
||||
regexp.MustCompile(`(?i)data:text/html`),
|
||||
regexp.MustCompile(`(?i)on\w+\s*=`),
|
||||
regexp.MustCompile(`(?i)<\s*img[^>]*src\s*=`),
|
||||
regexp.MustCompile(`(?i)<\s*iframe`),
|
||||
regexp.MustCompile(`(?i)<\s*object`),
|
||||
regexp.MustCompile(`(?i)<\s*embed`),
|
||||
regexp.MustCompile(`(?i)<\s*style`),
|
||||
regexp.MustCompile(`(?i)<\s*form`),
|
||||
regexp.MustCompile(`(?i)<\s*applet`),
|
||||
regexp.MustCompile(`(?i)<\s*meta`),
|
||||
}
|
||||
|
||||
for _, pattern := range suspiciousPatterns {
|
||||
if pattern.MatchString(value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue