Files
aiops/backend/pkg/agentcli/guardrail/sanitize.go
T
Logan.LiandCursor 2fd1624bec feat: 加固 Agent CLI 执行边界并更新模型目录
收紧 SSH 命令护栏、权限校验与远程执行会话,并同步主流大模型供应商列表。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 09:43:14 +08:00

121 lines
3.2 KiB
Go

// 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)
}
// SanitizeMap 返回脱敏后的参数副本,避免事件、审计和记忆泄露工具参数中的凭证。 // Logan.Li
func SanitizeMap(input map[string]interface{}) map[string]interface{} {
if input == nil {
return nil
}
sanitized, ok := sanitizeValue(input).(map[string]interface{})
if !ok {
return map[string]interface{}{}
}
return sanitized
}
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)
}