Redact the API key from all config errors and reject empty URL delimiters
An invalid extra-header name is no longer echoed, and every other New error that quotes caller-supplied text (structured output mode, header names) has the API key redacted first via a shared redactKey helper, also used for transport errors. A base URL containing "?" or "#" is rejected even when the query or fragment is empty, so endpoint paths can no longer land in either. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -627,6 +627,31 @@ func TestNewRejectsBadHeaderWithoutEchoingValue(t *testing.T) {
|
||||
assertNoSecret(t, err)
|
||||
}
|
||||
|
||||
// TestNewConfigErrorsNeverLeakKey covers every New error that names
|
||||
// caller-supplied text, each with the API key embedded in that text.
|
||||
func TestNewConfigErrorsNeverLeakKey(t *testing.T) {
|
||||
cases := map[string]Config{
|
||||
"key in invalid header name": {Headers: map[string]string{"Bearer " + testKey: "a"}},
|
||||
"key as invalid header name": {Headers: map[string]string{testKey + ":": "a"}},
|
||||
"key in name, bad value": {Headers: map[string]string{"X-" + testKey: "a\nb"}},
|
||||
"key in structured output": {StructuredOutput: StructuredOutput("Bearer " + testKey)},
|
||||
"key with quote in mode": {StructuredOutput: StructuredOutput(testKey + "\"\x00")},
|
||||
}
|
||||
for name, cfg := range cases {
|
||||
cfg.BaseURL = "https://example.com/v1"
|
||||
cfg.APIKey = testKey
|
||||
if cfg.StructuredOutput == "" {
|
||||
cfg.StructuredOutput = JSONSchema
|
||||
}
|
||||
_, err := New(cfg)
|
||||
if err == nil {
|
||||
t.Errorf("%s: New() = nil error", name)
|
||||
continue
|
||||
}
|
||||
assertNoSecret(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcceptHeader(t *testing.T) {
|
||||
for name, tc := range map[string]struct {
|
||||
headers map[string]string
|
||||
@@ -664,6 +689,9 @@ func TestNewRejectsBadConfig(t *testing.T) {
|
||||
"key, relative base": {BaseURL: "example.com/v1?key=" + testKey, StructuredOutput: JSONSchema},
|
||||
"key, ftp base": {BaseURL: "ftp://example.com/v1?key=" + testKey, StructuredOutput: JSONSchema},
|
||||
"key, unparseable": {BaseURL: "https://example.com/%zz?key=" + testKey, StructuredOutput: JSONSchema},
|
||||
"empty query": {BaseURL: "https://example.com/v1?", StructuredOutput: JSONSchema},
|
||||
"empty fragment": {BaseURL: "https://example.com/v1#", StructuredOutput: JSONSchema},
|
||||
"empty both": {BaseURL: "https://example.com/v1?#", StructuredOutput: JSONSchema},
|
||||
"unknown mode": {BaseURL: "https://example.com/v1", StructuredOutput: "json"},
|
||||
"no mode": {BaseURL: "https://example.com/v1"},
|
||||
"authorization hdr": {BaseURL: "https://example.com/v1", StructuredOutput: JSONSchema, Headers: map[string]string{"authorization": "Bearer x"}},
|
||||
|
||||
Reference in New Issue
Block a user