83 lines
2.2 KiB
Go
83 lines
2.2 KiB
Go
package security
|
|
|
|
import (
|
|
"html"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/microcosm-cc/bluemonday"
|
|
)
|
|
|
|
// XSSPolicy defines the sanitization policy
|
|
type XSSPolicy struct {
|
|
policy *bluemonday.Policy
|
|
}
|
|
|
|
// NewXSSPolicy creates a new XSS sanitization policy
|
|
func NewXSSPolicy() *XSSPolicy {
|
|
p := bluemonday.UGCPolicy()
|
|
|
|
// Allow basic formatting but strip scripts and dangerous attributes
|
|
p.AllowAttrs("href", "target", "rel").OnElements("a")
|
|
p.AllowAttrs("src", "alt", "width", "height").OnElements("img")
|
|
p.AllowElements("p", "br", "strong", "em", "u", "h1", "h2", "h3", "h4", "h5", "h6")
|
|
p.AllowElements("ul", "ol", "li")
|
|
|
|
return &XSSPolicy{policy: p}
|
|
}
|
|
|
|
// SanitizeHTML sanitizes HTML input, allowing safe tags
|
|
func (x *XSSPolicy) SanitizeHTML(input string) string {
|
|
return x.policy.Sanitize(input)
|
|
}
|
|
|
|
// SanitizeText completely escapes HTML entities for safe text display
|
|
func (x *XSSPolicy) SanitizeText(input string) string {
|
|
return html.EscapeString(input)
|
|
}
|
|
|
|
// SanitizeEmail sanitizes input for use in email contexts
|
|
func (x *XSSPolicy) SanitizeEmail(input string) string {
|
|
// For emails, we want to allow basic formatting but be strict
|
|
return strings.TrimSpace(x.SanitizeText(input))
|
|
}
|
|
|
|
// SanitizeURL sanitizes URL input
|
|
func (x *XSSPolicy) SanitizeURL(input string) string {
|
|
// Remove javascript: and data: schemes
|
|
dangerous := regexp.MustCompile(`(?i)^(javascript|data|vbscript):`)
|
|
if dangerous.MatchString(input) {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(input)
|
|
}
|
|
|
|
// SanitizePhoneNumber sanitizes phone number input
|
|
func (x *XSSPolicy) SanitizePhoneNumber(input string) string {
|
|
// Remove any HTML tags and trim whitespace
|
|
clean := regexp.MustCompile(`<[^>]*>`).ReplaceAllString(input, "")
|
|
return strings.TrimSpace(clean)
|
|
}
|
|
|
|
// ValidateAndSanitizeInput validates and sanitizes user input
|
|
func (x *XSSPolicy) ValidateAndSanitizeInput(input string, fieldType string) (string, error) {
|
|
if strings.TrimSpace(input) == "" {
|
|
return "", nil
|
|
}
|
|
|
|
switch fieldType {
|
|
case "text":
|
|
return x.SanitizeText(input), nil
|
|
case "html":
|
|
return x.SanitizeHTML(input), nil
|
|
case "email":
|
|
return x.SanitizeEmail(input), nil
|
|
case "url":
|
|
return x.SanitizeURL(input), nil
|
|
case "phone":
|
|
return x.SanitizePhoneNumber(input), nil
|
|
default:
|
|
return x.SanitizeText(input), nil
|
|
}
|
|
}
|