You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(websearch): Brave fetch follows redirects and can forward X-Subscription-Token cross-host #5409
The Brave branch of websearch (gsd-core/bin/lib/commands.cjs, ~line 2982) calls fetch('https://api.search.brave.com/res/v1/web/search?…', { headers: { 'X-Subscription-Token': apiKey }, … }) with no redirect option. The default is redirect: 'follow', and Node's fetch does not strip custom headers such as X-Subscription-Token on a cross-host redirect. If api.search.brave.com answers 3xx to another host, the API key is sent to that host.
What did you expect?
The API key is only ever sent to api.search.brave.com. A 3xx is treated as a failure and nothing is re-sent.
Steps to reproduce
Node v26.11.1 shows the header forwarding; the loopback script uses two local servers, not Brave itself:
Start server T on a port that logs req.headers['x-subscription-token'].
Start server R that answers 307 Location: http://localhost:<T>/x.
Every time a redirect to another host occurs (the fixed Brave endpoint does not redirect today, so this is a hardening gap, not an observed leak)
Impact
Low — Hardening: requires the Brave endpoint (or a path in front of it) to redirect cross-host.
Workaround (if any)
None needed today.
Additional context
Found while reviewing the fix for #5288 (reviewer-lane HTTP seam following redirects). Same class of defect, different call site, independent change. Suggested fix: pass redirect: 'manual' and treat any 3xx as a failed attempt.
Reproduced: yes (mechanism) — on Node v26.11.1 a custom header survives a cross-host 307 under default redirect: 'follow'; with redirect: 'manual' the 307 is returned and nothing is re-sent. Not an observed leak: the Brave endpoint does not redirect today, so this is hardening. Root cause:src/commands.cts:3278-3288 (cmdWebsearch) sends X-Subscription-Token with the default redirect policy Introduced by: long-standing Blast radius: low — one caller, tests in tests/commands.test.cjs Coupled (must not miss): the retry loop treats 429/5xx as retryable; a 3xx must be a non-retryable failure, not a retry. Sibling of the reviewer-lane HTTP fix for #5288. Regression test: a server answering 3xx to another host yields available: false with an error, issues no second request, and the token never reaches the second host
Evidence note: the graph tools (Memtrace) were unavailable for this sweep; the located symbol and line were read directly from next @ 72730d8 and the symptom reproduced against that tree.
Agent Brief
Category: bug Summary: the Brave search API key must never be sent to any host other than the Brave API host Current behavior: a redirect from the search endpoint is followed and the subscription token header is forwarded to the redirect target Desired behavior: any redirect response is treated as a failed attempt; nothing is re-sent Key interfaces: the websearch command's Brave request and its failure output Acceptance criteria: a 3xx response produces the standard unavailable/error result without a follow-up request; 200, 429/5xx retry behavior and the no-key skip are unchanged Out of scope: other HTTP call sites, changing the retry policy
Activity
trek-e commentedon Oct 14, 2026
Diagnosis
Reproduced: yes (mechanism) — on Node v26.11.1 a custom header survives a cross-host 307 under default
redirect: 'follow'; withredirect: 'manual'the 307 is returned and nothing is re-sent. Not an observed leak: the Brave endpoint does not redirect today, so this is hardening.Root cause:
src/commands.cts:3278-3288(cmdWebsearch) sendsX-Subscription-Tokenwith the default redirect policyIntroduced by: long-standing
Blast radius: low — one caller, tests in
tests/commands.test.cjsCoupled (must not miss): the retry loop treats 429/5xx as retryable; a 3xx must be a non-retryable failure, not a retry. Sibling of the reviewer-lane HTTP fix for #5288.
Regression test: a server answering 3xx to another host yields
available: falsewith an error, issues no second request, and the token never reaches the second hostEvidence note: the graph tools (Memtrace) were unavailable for this sweep; the located symbol and line were read directly from
next@ 72730d8 and the symptom reproduced against that tree.Agent Brief
Category: bug
Summary: the Brave search API key must never be sent to any host other than the Brave API host
Current behavior: a redirect from the search endpoint is followed and the subscription token header is forwarded to the redirect target
Desired behavior: any redirect response is treated as a failed attempt; nothing is re-sent
Key interfaces: the
websearchcommand's Brave request and its failure outputAcceptance criteria: a 3xx response produces the standard unavailable/error result without a follow-up request; 200, 429/5xx retry behavior and the no-key skip are unchanged
Out of scope: other HTTP call sites, changing the retry policy
fix(websearch): stop Brave fetch following redirects
test(websearch): prove token never reaches redirect target (open-gsd#…
fix(open-gsd#5409): stop Brave fetch following redirects
fix(#5409): stop Brave fetch following redirects (#5443)