Background
Follow-up from #1561 / #1585 (redact sensitive headers in the fetch log). That slice masks Authorization, Cookie, Set-Cookie, Proxy-Authorization, X-Api-Key, and x-mcp-remote-auth on the recorded log entry. But core/mcp/fetchTracking.ts records four things per request — url, headers, requestBody, and responseBody — and only headers is redacted. The secrets that ride in the body and URL of those same requests are still logged verbatim.
Claude's review of #1585 flagged this as legitimately out of scope for the headers slice but recommended a tracked follow-up so it doesn't fall through the cracks. There was no existing issue for it.
The gap
For an OAuth token-endpoint exchange, the Authorization header is now masked, yet:
requestBody — the token request POSTs client_secret, code, refresh_token, code_verifier in the form body → logged in plaintext.
responseBody — the token endpoint returns access_token / refresh_token / id_token → logged in plaintext.
url — the full URL including query string is stored; some flows carry code/tokens as query params → logged verbatim.
Net: the network log still leaks the exact credentials the header redaction was meant to protect.
Scope
In core/mcp/fetchTracking.ts, before an entry reaches any sink, redact sensitive material in:
- Request/response bodies — for form-encoded and JSON bodies, redact known-sensitive fields (
client_secret, code, refresh_token, access_token, id_token, code_verifier, client_assertion, assertion, password, token). Preserve the surrounding shape so the log stays useful; replace only the values. Leave non-sensitive / non-parseable bodies untouched (best-effort parse, never throw).
- URL query strings — redact the same sensitive param names in the stored
url while keeping the path + non-sensitive params readable.
Reuse the header slice's REDACTED_HEADER_VALUE-style sentinel and case-insensitive matching. Live outbound requests must remain untouched — only the logged copy is redacted.
Acceptance
- OAuth token request/response bodies and any token-bearing URL query params show the redaction sentinel in the fetch log; live requests are byte-identical to before.
- Non-sensitive bodies/URLs are unchanged and still logged.
- Malformed/unparseable bodies don't throw — they log as-is (or as an opaque redaction if they can't be safely inspected).
- Per-file coverage ≥90 on all four dimensions for the touched code, expected-error output suppressed in tests.
Refs: #1561, #1585, tracking #1579.
Background
Follow-up from #1561 / #1585 (redact sensitive headers in the fetch log). That slice masks
Authorization,Cookie,Set-Cookie,Proxy-Authorization,X-Api-Key, andx-mcp-remote-authon the recorded log entry. Butcore/mcp/fetchTracking.tsrecords four things per request —url,headers,requestBody, andresponseBody— and onlyheadersis redacted. The secrets that ride in the body and URL of those same requests are still logged verbatim.Claude's review of #1585 flagged this as legitimately out of scope for the headers slice but recommended a tracked follow-up so it doesn't fall through the cracks. There was no existing issue for it.
The gap
For an OAuth token-endpoint exchange, the
Authorizationheader is now masked, yet:requestBody— the token request POSTsclient_secret,code,refresh_token,code_verifierin the form body → logged in plaintext.responseBody— the token endpoint returnsaccess_token/refresh_token/id_token→ logged in plaintext.url— the full URL including query string is stored; some flows carrycode/tokens as query params → logged verbatim.Net: the network log still leaks the exact credentials the header redaction was meant to protect.
Scope
In
core/mcp/fetchTracking.ts, before an entry reaches any sink, redact sensitive material in:client_secret,code,refresh_token,access_token,id_token,code_verifier,client_assertion,assertion,password,token). Preserve the surrounding shape so the log stays useful; replace only the values. Leave non-sensitive / non-parseable bodies untouched (best-effort parse, never throw).urlwhile keeping the path + non-sensitive params readable.Reuse the header slice's
REDACTED_HEADER_VALUE-style sentinel and case-insensitive matching. Live outbound requests must remain untouched — only the logged copy is redacted.Acceptance
Refs: #1561, #1585, tracking #1579.