Files
tm_back/pkg/security/xss.go
T
2025-12-07 23:52:17 +03:30

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
}
}