Files
2026-07-13 13:00:08 +08:00

58 lines
2.2 KiB
Go

package capdiag
import (
"strings"
"testing"
)
func TestSanitizeErrTextRedactsSecretsAndPaths(t *testing.T) {
home := t.TempDir()
ws := t.TempDir()
in := "stdio plugin \"x\": command \"npx\" not found on PATH; PATH=\"" + home + "/bin:/usr/bin\" Bearer sk-secret-token " +
ws + "/secret.env stderr: Authorization=Bearer abc.def"
out := sanitizeErrTextWithPaths(in, ws, home)
if strings.Contains(out, home) {
t.Fatalf("home path leaked: %q", out)
}
if strings.Contains(out, "sk-secret") || strings.Contains(out, "abc.def") {
t.Fatalf("token leaked: %q", out)
}
if strings.Contains(out, "PATH=\""+home) {
t.Fatalf("PATH value leaked: %q", out)
}
if !strings.Contains(out, "<redacted>") && !strings.Contains(out, "Bearer <redacted>") {
t.Fatalf("expected redaction markers in %q", out)
}
}
func TestSanitizeErrTextRedactsHTTPBodyCredentialShapes(t *testing.T) {
// An HTTP transport error carries up to 4KB of raw response body; none of
// its credential shapes may survive into the shareable report.
in := `http 401: {"access_token":"sk-live-secret","x-api-key":"header-secret","password":"pw-secret"} Cookie: session=cookie-secret`
out := sanitizeErrText(in)
for _, leaked := range []string{"sk-live-secret", "header-secret", "pw-secret", "cookie-secret"} {
if strings.Contains(out, leaked) {
t.Fatalf("credential leaked %q in %q", leaked, out)
}
}
if !strings.Contains(out, "http 401") {
t.Fatalf("status context lost: %q", out)
}
}
func TestSanitizeErrTextRedactsVendorTokenShapes(t *testing.T) {
cases := []struct{ name, in, leaked string }{
{"jwt", "stderr: jwt eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.sflKxwRJSMeKKF2QT4fwpMeJf36POk6yJVadQssw5c", "eyJhbGciOiJIUzI1NiJ9"},
{"github", "stderr: fatal: ghp_abcdefghijklmnopqrstuvwxyz123456", "ghp_abcdefghijklmnopqrstuvwxyz123456"},
{"openai", "stderr: invalid key sk-proj-abcdefghijklmnop1234", "sk-proj-abcdefghijklmnop1234"},
{"colon-header", "http 403: x-api-key: header-secret-value", "header-secret-value"},
{"set-cookie", "http 401: Set-Cookie: sid=abc123def456ghi; Path=/", "abc123def456ghi"},
}
for _, tc := range cases {
out := sanitizeErrText(tc.in)
if strings.Contains(out, tc.leaked) {
t.Fatalf("%s: credential leaked in %q", tc.name, out)
}
}
}