Skip to content

core: redact sensitive fields in fetch-log request/response bodies + URL query strings #1593

Description

@cliffhall

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:

  1. 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).
  2. 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.

Metadata

Metadata

Assignees

Labels

v2Issues and PRs for v2

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions