update
This commit is contained in:
1 parent
0690285147
commit
5618cd2738
154 files changed
+5021
-3161
No files matched your search
@@ -0,0 +1,108 @@
|
||||
// Package guardrail 提供 Agent CLI 输入输出治理能力。 // Logan.Li
|
||||
package guardrail
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var sensitivePatterns = []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)(bearer\s+)[a-z0-9._~+/=-]{16,}`),
|
||||
regexp.MustCompile(`(?i)((?:password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|secret[_-]?key)\s*[:=]\s*)[^\s'"&]+`),
|
||||
regexp.MustCompile(`(?i)((?:mysql|postgres|postgresql|redis|mongodb)://[^:\s/@]+:)[^@\s]+(@)`),
|
||||
regexp.MustCompile(`(?is)-----BEGIN [A-Z ]*PRIVATE KEY-----.*?-----END [A-Z ]*PRIVATE KEY-----`),
|
||||
regexp.MustCompile(`(?i)((?:Cookie|Set-Cookie):\s*)[^\r\n]+`),
|
||||
regexp.MustCompile(`(?i)(AKIA[0-9A-Z]{16})`),
|
||||
}
|
||||
|
||||
var sensitiveKeys = map[string]bool{
|
||||
"password": true, "passwd": true, "pwd": true, "secret": true,
|
||||
"token": true, "api_key": true, "apikey": true, "access_key": true,
|
||||
"secret_key": true, "private_key": true, "cookie": true,
|
||||
}
|
||||
|
||||
// SanitizeText 脱敏工具输出、LLM 文本和错误信息,避免敏感信息进入前端/DB/记忆。 // Logan.Li
|
||||
func SanitizeText(input string) string {
|
||||
if input == "" {
|
||||
return ""
|
||||
}
|
||||
out := input
|
||||
for _, re := range sensitivePatterns {
|
||||
out = re.ReplaceAllStringFunc(out, func(match string) string {
|
||||
if strings.Contains(match, "PRIVATE KEY") {
|
||||
return "[REDACTED_PRIVATE_KEY]"
|
||||
}
|
||||
sub := re.FindStringSubmatch(match)
|
||||
if len(sub) >= 3 {
|
||||
return sub[1] + "[REDACTED]" + sub[2]
|
||||
}
|
||||
if len(sub) >= 2 {
|
||||
return sub[1] + "[REDACTED]"
|
||||
}
|
||||
return "[REDACTED]"
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// SanitizeJSON 脱敏 JSON 文本;非法 JSON 时退回文本脱敏。 // Logan.Li
|
||||
func SanitizeJSON(raw string) string {
|
||||
if strings.TrimSpace(raw) == "" {
|
||||
return raw
|
||||
}
|
||||
var v interface{}
|
||||
if err := json.Unmarshal([]byte(raw), &v); err != nil {
|
||||
return SanitizeText(raw)
|
||||
}
|
||||
v = sanitizeValue(v)
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return SanitizeText(raw)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func sanitizeValue(v interface{}) interface{} {
|
||||
switch val := v.(type) {
|
||||
case map[string]interface{}:
|
||||
out := make(map[string]interface{}, len(val))
|
||||
for k, item := range val {
|
||||
if sensitiveKeys[strings.ToLower(strings.ReplaceAll(k, "-", "_"))] {
|
||||
out[k] = "[REDACTED]"
|
||||
continue
|
||||
}
|
||||
out[k] = sanitizeValue(item)
|
||||
}
|
||||
return out
|
||||
case []interface{}:
|
||||
for i := range val {
|
||||
val[i] = sanitizeValue(val[i])
|
||||
}
|
||||
return val
|
||||
case string:
|
||||
return SanitizeText(val)
|
||||
default:
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// NewTraceID 生成短 trace id,便于串联一次 Agent 任务。 // Logan.Li
|
||||
func NewTraceID() string {
|
||||
return "tr-" + randomHex(12)
|
||||
}
|
||||
|
||||
// NewSpanID 生成短 span id,便于串联工具和消息事件。 // Logan.Li
|
||||
func NewSpanID() string {
|
||||
return "sp-" + randomHex(8)
|
||||
}
|
||||
|
||||
func randomHex(n int) string {
|
||||
buf := make([]byte, n)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return "0000000000000000"
|
||||
}
|
||||
return hex.EncodeToString(buf)
|
||||
}
|
||||
Reference in new issue
Block a user