feat(sql): SQL Injection

This commit is contained in:
Björn Benouarets
2025-11-06 11:16:01 +01:00
parent 1f5f07e624
commit 10110071eb
7 changed files with 206 additions and 26 deletions

View File

@@ -2,6 +2,7 @@ package utils
import (
"fmt"
"regexp"
"strings"
)
@@ -12,7 +13,6 @@ func SQLQuoteIdent(id string) string {
func SQLQuoteValue(value any) string {
switch v := value.(type) {
case string:
// Escape single quotes by doubling them (PostgreSQL standard)
escaped := strings.ReplaceAll(v, "'", "''")
return fmt.Sprintf("'%s'", escaped)
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
@@ -24,8 +24,57 @@ func SQLQuoteValue(value any) string {
case nil:
return "NULL"
}
// For unknown types, convert to string and escape
str := fmt.Sprintf("%v", value)
escaped := strings.ReplaceAll(str, "'", "''")
return fmt.Sprintf("'%s'", escaped)
}
var identifierRe = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]{0,62}$`)
func IsValidIdentifier(id string) bool {
return identifierRe.MatchString(id)
}
var allowedOnActions = map[string]bool{
"CASCADE": true,
"SET NULL": true,
"NO ACTION": true,
"RESTRICT": true,
"SET DEFAULT": true,
}
func SanitizeOnAction(s string) (string, error) {
if strings.TrimSpace(s) == "" {
return "", nil
}
u := strings.ToUpper(strings.Join(strings.Fields(s), " "))
if allowedOnActions[u] {
return u, nil
}
return "", fmt.Errorf("invalid action: %q", s)
}
var allowedDefaultFuncs = map[string]bool{
"CURRENT_TIMESTAMP": true,
"NOW()": true,
"UUID_GENERATE_V4()": true,
}
func IsValidDefault(val string) bool {
v := strings.TrimSpace(val)
if v == "" {
return false
}
if regexp.MustCompile(`^[+-]?\d+(\.\d+)?$`).MatchString(v) {
return true
}
if strings.HasPrefix(v, "'") && strings.HasSuffix(v, "'") {
return true
}
if allowedDefaultFuncs[strings.ToUpper(v)] {
return true
}
return false
}