Skip to content

Harden AI providers: no token leak in errors, request timeouts#342

Merged
clcollins merged 2 commits into
mainfrom
srepd/ai-provider-hardening
Jul 9, 2026
Merged

Harden AI providers: no token leak in errors, request timeouts#342
clcollins merged 2 commits into
mainfrom
srepd/ai-provider-hardening

Conversation

@clcollins

Copy link
Copy Markdown
Owner

Summary

  1. Token leak fix: on non-200 responses both providers interpolated the
    response body into the returned error. A proxy/gateway that echoes the
    Authorization: Bearer <token> header in its error body would leak the token
    into logs. Now return status code only (matching the Healthy methods) —
    the token is only ever in the request header, so this removes the leak.
  2. Timeouts: added ensureTimeout applying a default 60s deadline to
    non-streaming Query/Healthy when the caller's context has none.
    Not applied to StreamQuery or the shared http.Client.Timeout — either
    would truncate long token streams.

Test plan

  • TDD: leak + timeout tests written first (red), then green
  • *_DoesNotLeakTokenInError — server echoes the Authorization header in a
    401 body; error contains 401 but never the token
  • TestOpenAIQuery_AppliesDefaultTimeout — hung server + deadline-less
    context returns promptly
  • Existing *_ServerError tests (Contains("500")) still pass — status retained
  • make test-all green (fmt, vet, lint, test, race, test-fixtures)

No README trigger files touched.

🤖 Generated with Claude Code

On non-200 responses both providers interpolated the response body into the
returned error. A proxy that echoes the Authorization header in its error body
would leak the API token into logs. Drop the body — return status code only,
matching the Healthy methods. The token is only ever in the request header, so
status-only removes the leak regardless of what the server echoes.

Add defense-in-depth timeouts: defaultRequestTimeout + ensureTimeout apply a
default deadline to non-streaming Query/Healthy when the caller's context has
none. Not applied to StreamQuery or the shared http.Client.Timeout, either of
which would truncate long token streams.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.42%. Comparing base (bfb9516) to head (cf7191b).

Files with missing lines Patch % Lines
pkg/ai/provider.go 50.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #342      +/-   ##
==========================================
+ Coverage   66.38%   66.42%   +0.04%     
==========================================
  Files          50       51       +1     
  Lines        8160     8170      +10     
==========================================
+ Hits         5417     5427      +10     
  Misses       2368     2368              
  Partials      375      375              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@clcollins clcollins merged commit ea0b98a into main Jul 9, 2026
10 checks passed
@clcollins clcollins deleted the srepd/ai-provider-hardening branch July 9, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants