Skip to content

Commit ecdc846

Browse files
refactor: unify redactHeaderValue and MaskSecret funcs
1 parent 6c88bec commit ecdc846

4 files changed

Lines changed: 6 additions & 73 deletions

File tree

intercept/apidump/apidump.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"cdr.dev/slog/v3"
1616

17+
"github.com/coder/aibridge/utils"
1718
"github.com/coder/quartz"
1819
"github.com/google/uuid"
1920
"github.com/tidwall/pretty"
@@ -186,7 +187,7 @@ func (d *dumper) writeRedactedHeaders(w io.Writer, headers http.Header, sensitiv
186187
}
187188

188189
if isSensitive {
189-
value = redactHeaderValue(value)
190+
value = utils.MaskSecret(value)
190191
}
191192
_, err := fmt.Fprintf(w, "%s: %s\r\n", key, value)
192193
if err != nil {

intercept/apidump/apidump_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestBridgedMiddleware_RedactsSensitiveRequestHeaders(t *testing.T) {
7373
// Verify sensitive headers ARE present but redacted
7474
require.Contains(t, content, "Authorization: Bear...2345")
7575
require.Contains(t, content, "X-Api-Key: secr...alue")
76-
require.Contains(t, content, "Cookie: sess...c123") // "session=abc123" is 14 chars, so first 4 + last 4
76+
require.Contains(t, content, "Cookie: se...23") // "session=abc123" is 14 chars, reveal=2
7777

7878
// Verify the full secret values are NOT present
7979
require.NotContains(t, content, "sk-secret-key-12345")
@@ -133,8 +133,8 @@ func TestBridgedMiddleware_RedactsSensitiveResponseHeaders(t *testing.T) {
133133
// Verify sensitive headers are present but redacted
134134
require.Contains(t, content, "Set-Cookie: sess...cure")
135135
// Note: Go canonicalizes WWW-Authenticate to Www-Authenticate
136-
// "Bearer realm=\"api\"" = 18 chars, first 4 = "Bear", last 4 = "api\""
137-
require.Contains(t, content, "Www-Authenticate: Bear...api\"")
136+
// "Bearer realm=\"api\"" = 18 chars, reveal=2, first 2 = "Be", last 2 = "i\""
137+
require.Contains(t, content, "Www-Authenticate: Be...i\"")
138138

139139
// Verify full secret values are NOT present
140140
require.NotContains(t, content, "secret123")

intercept/apidump/headers.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,3 @@ var sensitiveResponseHeaders = map[string]struct{}{
1818
"Www-Authenticate": {},
1919
"Proxy-Authenticate": {},
2020
}
21-
22-
// redactHeaderValue redacts a sensitive header value, showing only partial content.
23-
// For values >= 8 bytes: shows first 4 and last 4 bytes with "..." in between.
24-
// For values < 8 bytes: shows first and last byte with "..." in between.
25-
func redactHeaderValue(value string) string {
26-
if len(value) >= 8 {
27-
return value[:4] + "..." + value[len(value)-4:]
28-
}
29-
if len(value) >= 2 {
30-
return value[:1] + "..." + value[len(value)-1:]
31-
}
32-
// Single character or empty - just return as-is
33-
return value
34-
}

intercept/apidump/headers_test.go

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,60 +12,6 @@ import (
1212
"github.com/stretchr/testify/require"
1313
)
1414

15-
func TestRedactHeaderValue(t *testing.T) {
16-
t.Parallel()
17-
18-
tests := []struct {
19-
name string
20-
input string
21-
expected string
22-
}{
23-
{
24-
name: "empty string",
25-
input: "",
26-
expected: "",
27-
},
28-
{
29-
name: "single char",
30-
input: "a",
31-
expected: "a",
32-
},
33-
{
34-
name: "two chars",
35-
input: "ab",
36-
expected: "a...b",
37-
},
38-
{
39-
name: "seven chars",
40-
input: "abcdefg",
41-
expected: "a...g",
42-
},
43-
{
44-
name: "eight chars - threshold",
45-
input: "abcdefgh",
46-
expected: "abcd...efgh",
47-
},
48-
{
49-
name: "long value",
50-
input: "Bearer sk-secret-key-12345",
51-
expected: "Bear...2345",
52-
},
53-
{
54-
name: "realistic api key",
55-
input: "sk-proj-abc123xyz789",
56-
expected: "sk-p...z789",
57-
},
58-
}
59-
60-
for _, tc := range tests {
61-
t.Run(tc.name, func(t *testing.T) {
62-
t.Parallel()
63-
result := redactHeaderValue(tc.input)
64-
require.Equal(t, tc.expected, result)
65-
})
66-
}
67-
}
68-
6915
func TestSensitiveHeaderLists(t *testing.T) {
7016
t.Parallel()
7117

@@ -140,7 +86,7 @@ func TestWriteRedactedHeaders(t *testing.T) {
14086
name: "sensitive header redacted",
14187
headers: http.Header{"Set-Cookie": {"session=abcdefghij"}},
14288
sensitive: sensitiveResponseHeaders,
143-
expected: "Set-Cookie: sess...ghij\r\n",
89+
expected: "Set-Cookie: se...ij\r\n",
14490
},
14591
{
14692
name: "multi-value header",

0 commit comments

Comments
 (0)