Repository navigation
fix: redact provider credentials from logs and API responses - #279
Open
guofeng201507 wants to merge 1 commit into
Open
guofeng201507 wants to merge 1 commit into
guofeng201507 wants to merge 1 commit into
Conversation
Provider API keys could reach application logs — and in one path the API response — because the key travels in the request URL and `requests` embeds the URL inside its exception messages. - Google Gemini: send the key via the documented `x-goog-api-key` header instead of the `?key=` query parameter, so it never appears in a URL-derived string. - Add `app.utils.redaction.redact_secrets()` and route every exception-derived string through it before logging, re-raising, or returning it (scrubs query-parameter secrets and `Bearer` tokens while keeping host/path so failures stay debuggable). - Apply the same scrub to the settings connection test, where the exception text was both logged and returned to the client as `msg`. An invalid or expired key (HTTP 403) is the most common trigger, so the leak fires exactly when someone is troubleshooting. Backward compatibility: the Gemini change relies on the official `x-goog-api-key` header; a Gemini-compatible proxy that only accepts `?key=` would need updating. Testing: `pytest tests/test_llm_litellm_provider.py` -> 37 passed (3 new regression tests, 34 pre-existing unchanged).
guofeng201507
added a commit
to guofeng201507/SharkQuantDinger
that referenced
this pull request
Oct 9, 2026
Provider API keys could reach application logs — and in one path the API response — because the key travels in the request URL and `requests` embeds the URL inside its exception messages. The most common trigger is an ordinary failure (invalid key -> HTTP 403, or a network timeout), i.e. exactly when someone is troubleshooting. - Google Gemini: send the key via the documented `x-goog-api-key` header instead of the `?key=` query parameter. - Add `app.utils.redaction.redact_secrets()` and route every exception-derived string through it before logging, re-raising, or returning it (scrubs query-parameter secrets and `Bearer` tokens while keeping host/path so failures stay debuggable). - Apply the same scrub to the settings connection test, where the exception text was logged and returned to the client as `msg`. An upstream PR with the same change is open as OpenByteInc#279. Testing: pytest tests/test_llm_litellm_provider.py -> 37 passed (3 new regression tests, 34 pre-existing unchanged).
guofeng201507
added a commit
to guofeng201507/SharkQuantDinger
that referenced
this pull request
Oct 9, 2026
Send credentials only in headers (x-goog-api-key for Gemini) and drop the redact_secrets dependency, so the probe does not rely on PR OpenByteInc#279 and can be upstreamed as a standalone patch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed and why
Provider API keys could end up in application logs — and in one path in the API
response — because the key was carried in the request URL and
requestsembedsthe URL inside its exception messages. The most common trigger is an ordinary
failure: an invalid/expired key (HTTP 403) or a network timeout, i.e. exactly
when someone is troubleshooting.
backend_api_python/app/services/llm.py—LLMService._call_google_gemini()url = f"{base_url}/models/{model}:generateContent?key={api_key}"x-goog-api-keyrequest headerbackend_api_python/app/utils/redaction.py(new)redact_secrets()scrubskey=,api_key=,token=,secret=,password=andBearer <token>from a string, keeping the host/path sofailures stay debuggable.
backend_api_python/app/services/llm.pyredact_secrets()beforebeing logged, re-raised, or written into the returned
reportfield: the HTTPerror, request error, invalid-data, aggregate error, alternative-provider
fallback, and the
_llm_postconnection error paths.backend_api_python/app/routes/settings.py—test_connection()msg, so theFinnhub key (
...?symbol=AAPL&token=...) could be displayed in the UI. Bothplaces are now scrubbed.
How to test
Manual: configure the Google provider with a key, make the call fail (invalid
key → 403, unreachable
GOOGLE_BASE_URL, or blockgenerativelanguage.googleapis.com), trigger any AI feature, then check thebackend log. Before:
...:generateContent?key=AIza...; after:...?key=<redacted>.Automated:
Includes 3 new regression tests: the Gemini key is absent from the URL and
present in the header; the scrubber removes query-parameter secrets and bearer
tokens; harmless text passes through unchanged. Run on CPython 3.12 using the
project's own backend image. The 34 pre-existing tests are unchanged.
Backward compatibility
The Gemini change relies on the official
x-goog-api-keyheader, which theGemini REST API documents. A Gemini-compatible proxy that only accepts
?key=would need updating.
Notes
Filed as a normal fix rather than a private vulnerability report — happy to
re-route through the channel described in
SECURITY.mdif you would prefer that.