Files
antrean-anjungan/internal/utils/validation/sanitizer.go
2025-10-23 04:25:28 +07:00

173 lines
4.4 KiB
Go

package validation
import (
"html"
"regexp"
"strings"
"unicode/utf8"
)
// InputSanitizer provides comprehensive input sanitization
type InputSanitizer struct {
maxLength int
}
// NewInputSanitizer creates a new input sanitizer
func NewInputSanitizer(maxLength int) *InputSanitizer {
return &InputSanitizer{maxLength: maxLength}
}
// SanitizeString performs comprehensive sanitization on a string
func (s *InputSanitizer) SanitizeString(input string) string {
if input == "" {
return input
}
// Check length limit
if utf8.RuneCountInString(input) > s.maxLength {
input = string([]rune(input)[:s.maxLength])
}
// Remove null bytes and control characters
input = strings.Map(func(r rune) rune {
if r < 32 && r != 9 && r != 10 && r != 13 { // Allow tab, LF, CR
return -1
}
return r
}, input)
// HTML escape to prevent XSS
input = html.EscapeString(input)
// Remove potentially dangerous patterns
dangerousPatterns := []string{
`<script[^>]*>.*?</script>`,
`<iframe[^>]*>.*?</iframe>`,
`<object[^>]*>.*?</object>`,
`<embed[^>]*>.*?</embed>`,
`javascript:`,
`vbscript:`,
`data:`,
`on\w+\s*=`,
}
for _, pattern := range dangerousPatterns {
re := regexp.MustCompile(`(?i)` + pattern)
input = re.ReplaceAllString(input, "")
}
// Trim whitespace
return strings.TrimSpace(input)
}
// SanitizeSQLInput sanitizes input specifically for SQL queries
func (s *InputSanitizer) SanitizeSQLInput(input string) string {
input = s.SanitizeString(input)
// Additional SQL-specific sanitization
sqlPatterns := []string{
`;`, `--`, `/*`, `*/`, `@@`, `@`,
`xp_`, `sp_`, `exec`, `execute`,
`information_schema`, `sysobjects`,
`syscolumns`, `sysdatabases`,
}
for _, pattern := range sqlPatterns {
input = strings.ReplaceAll(input, pattern, "")
}
return input
}
// ValidateSQLSafe checks if input is safe for SQL queries
func (s *InputSanitizer) ValidateSQLSafe(input string) bool {
if input == "" {
return true
}
// Check for SQL injection patterns
suspiciousPatterns := []string{
"union select", "union all select",
"select.*from", "insert.*into", "update.*set", "delete.*from",
"drop table", "drop database", "alter table", "create table",
"information_schema", "sysobjects", "syscolumns", "sysdatabases",
"mysql.", "pg_", "sqlite_",
";--", "/*", "*/", "@@",
"script>", "<script",
"javascript:", "vbscript:",
"onload=", "onerror=", "eval(", "alert(",
}
lowerInput := strings.ToLower(input)
for _, pattern := range suspiciousPatterns {
if strings.Contains(lowerInput, pattern) {
return false
}
}
return true
}
// SanitizeJSON sanitizes JSON input
func (s *InputSanitizer) SanitizeJSON(input string) string {
input = s.SanitizeString(input)
// Remove JSON-specific dangerous patterns
jsonPatterns := []string{
`{"\w+":\s*"[^"]*javascript:[^"]*"}`,
`{"\w+":\s*"[^"]*vbscript:[^"]*"}`,
`{"\w+":\s*"[^"]*data:[^"]*"}`,
}
for _, pattern := range jsonPatterns {
re := regexp.MustCompile(`(?i)` + pattern)
input = re.ReplaceAllString(input, "")
}
return input
}
// SanitizeFilename sanitizes filename inputs
func (s *InputSanitizer) SanitizeFilename(filename string) string {
filename = s.SanitizeString(filename)
// Remove path traversal attempts
filename = strings.ReplaceAll(filename, "../", "")
filename = strings.ReplaceAll(filename, "..\\", "")
// Remove dangerous characters for filenames
dangerousChars := []string{"/", "\\", ":", "*", "?", "\"", "<", ">", "|"}
for _, char := range dangerousChars {
filename = strings.ReplaceAll(filename, char, "")
}
return filename
}
// BatchSanitize sanitizes multiple inputs at once
func (s *InputSanitizer) BatchSanitize(inputs map[string]string) map[string]string {
sanitized := make(map[string]string)
for key, value := range inputs {
sanitized[key] = s.SanitizeString(value)
}
return sanitized
}
// IsValidInputLength checks if input length is within acceptable limits
func (s *InputSanitizer) IsValidInputLength(input string, minLen, maxLen int) bool {
length := utf8.RuneCountInString(input)
return length >= minLen && length <= maxLen
}
// ContainsHTML checks if input contains HTML tags
func (s *InputSanitizer) ContainsHTML(input string) bool {
htmlRegex := regexp.MustCompile(`<[^>]+>`)
return htmlRegex.MatchString(input)
}
// StripHTML removes HTML tags from input
func (s *InputSanitizer) StripHTML(input string) string {
htmlRegex := regexp.MustCompile(`<[^>]+>`)
return htmlRegex.ReplaceAllString(input, "")
}