// Package sanitizer 提供 Access、Audit 与 Integration 共用的敏感字段清理能力。 package sanitizer import ( "crypto/sha256" "encoding/hex" "fmt" "strings" "github.com/bytedance/sonic" ) var forbiddenFragments = []string{ "password", "passwd", "credential", "operation_password", "verification_code", "captcha", "access_token", "refresh_token", "authorization", "cookie", "secret", "private_key", "public_key", "encoding_aes_key", "callback_token", "signature", "sign", "nonce", "media_id", "signed_url", "private_url", "qr_content", "id_card", "identity_number", } // IsForbiddenField 判断字段是否禁止进入普通日志、审计或外部交互摘要。 func IsForbiddenField(key string) bool { normalized := strings.ToLower(strings.NewReplacer("-", "_", ".", "_").Replace(key)) for _, fragment := range forbiddenFragments { if strings.Contains(normalized, fragment) { return true } } if strings.HasSuffix(normalized, "_key") || normalized == "key" || strings.HasSuffix(normalized, "_url") || normalized == "url" { return true } return false } // MarshalSummary 递归删除禁止字段并返回 sonic 编码的安全 JSON。 func MarshalSummary(value any) ([]byte, error) { if value == nil { return nil, nil } encoded, err := sonic.Marshal(value) if err != nil { return nil, err } var normalized any if err := sonic.Unmarshal(encoded, &normalized); err != nil { return nil, err } RemoveForbiddenFields(normalized) return sonic.Marshal(normalized) } // RemoveForbiddenFields 原地递归删除 Map 或数组中的禁止字段。 func RemoveForbiddenFields(value any) { switch typed := value.(type) { case map[string]any: for key, item := range typed { if IsForbiddenField(key) { delete(typed, key) continue } RemoveForbiddenFields(item) } case []any: for _, item := range typed { RemoveForbiddenFields(item) } } } // TextSummary 将不可信外部文本转换为不可逆大小和哈希摘要。 func TextSummary(value string) string { if value == "" { return "" } sum := sha256.Sum256([]byte(value)) return fmt.Sprintf("外部文本摘要 bytes=%d sha256=%s", len(value), hex.EncodeToString(sum[:8])) }