mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-08-09 00:25:38 +00:00
- Add concurrent tests for session, memory, agent stores (race detection) - Add task lifecycle edge case tests (BlockedUnblockFlow, RaceToClaimSameTask) - Strengthen scrub_test.go assertions to verify exact output - Add security edge case validation to ValidateUserID (null bytes, control chars, unicode format chars)
45 lines
1.3 KiB
Go
45 lines
1.3 KiB
Go
package store
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
// MaxUserIDLength is the maximum allowed length for user identifier strings
|
|
// (user_id, owner_id, granted_by, requested_by, reviewed_by, etc.).
|
|
// Matches the VARCHAR(255) constraint in the database schema.
|
|
const MaxUserIDLength = 255
|
|
|
|
// ValidateUserID validates user identifiers for length and dangerous characters.
|
|
// Defense-in-depth: SQL injection is handled by parameterized queries, but we
|
|
// also reject clearly malicious patterns at the validation layer.
|
|
func ValidateUserID(id string) error {
|
|
if len(id) > MaxUserIDLength {
|
|
return fmt.Errorf("user identifier too long: %d chars (max %d)", len(id), MaxUserIDLength)
|
|
}
|
|
|
|
// Reject null bytes
|
|
if strings.ContainsRune(id, '\x00') {
|
|
return fmt.Errorf("user identifier contains null byte")
|
|
}
|
|
|
|
// Reject control characters (below space, including tab/newline/carriage return)
|
|
for _, r := range id {
|
|
if r < 32 {
|
|
return fmt.Errorf("user identifier contains control character: %U", r)
|
|
}
|
|
// Reject dangerous unicode categories
|
|
if unicode.Is(unicode.Cf, r) { // Format characters (ZWJ, RTL override, etc.)
|
|
return fmt.Errorf("user identifier contains format character: %U", r)
|
|
}
|
|
}
|
|
|
|
// Reject BOM
|
|
if strings.HasPrefix(id, "\uFEFF") {
|
|
return fmt.Errorf("user identifier starts with BOM")
|
|
}
|
|
|
|
return nil
|
|
}
|