b7360439ab
补齐 Harness 输出侧:harness.RedactSecrets 识别并脱敏 sk-/AKIA/JWT/Bearer 等 疑似密钥令牌(纯逻辑 + 单测)。runAgent 在每个 token 分片发射前调用(流式无法回收 已发,故逐片脱敏),脱敏会累计进 b.answer(写回历史也是脱敏版);有命中则在 运行·观测打一条'已脱敏 N 处'轨迹。 注:跨分片的密钥可能漏(流式现实),逐片为最佳努力;生产可加滑窗缓冲增强。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
40 lines
1.1 KiB
Go
40 lines
1.1 KiB
Go
package harness
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRedactSecrets(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
wantN int
|
|
mustGone string // 脱敏后不应再出现的子串
|
|
}{
|
|
{"我的 key 是 sk-912cf85b16d04b22bcb95f4576423bfb 别外传", 1, "sk-912cf85b16d04b22bcb95f4576423bfb"},
|
|
{"token: AKIAIOSFODNN7EXAMPLE", 1, "AKIAIOSFODNN7EXAMPLE"},
|
|
{"Authorization: Bearer abcdef0123456789ABCDEF", 1, "abcdef0123456789ABCDEF"},
|
|
{"jwt eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.abcd1234 完事", 1, "eyJhbGciOiJIUzI1NiJ9"},
|
|
}
|
|
for _, c := range cases {
|
|
out, n := RedactSecrets(c.in)
|
|
if n != c.wantN {
|
|
t.Errorf("RedactSecrets(%q) 命中数=%d want %d", c.in, n, c.wantN)
|
|
}
|
|
if strings.Contains(out, c.mustGone) {
|
|
t.Errorf("脱敏后仍含密钥: %q", out)
|
|
}
|
|
if !strings.Contains(out, redactMark) {
|
|
t.Errorf("应含脱敏标记: %q", out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRedactSecrets_Clean(t *testing.T) {
|
|
in := "这是一段正常的回答,介绍杭州西湖的历史与十景。"
|
|
out, n := RedactSecrets(in)
|
|
if n != 0 || out != in {
|
|
t.Errorf("正常文本不应被改动: n=%d out=%q", n, out)
|
|
}
|
|
}
|