Repository navigation
fix(redact): close header-credential leaks #50423 missed (JSON secret headers + Cookie/Set-Cookie) - #50514
fix(redact): close header-credential leaks #50423 missed (JSON secret headers + Cookie/Set-Cookie)#50514r266-tech wants to merge 2 commits into
Conversation
tonydwb
left a comment
There was a problem hiding this comment.
Review: fix(redact): header-credential leaks in JS
Security fix — closes two redaction gaps:
- Secret headers serialized as JSON (
"x-api-key": "<value>") — bare-header regex can't match the closing quote. Opaque custom/local-backend keys leaked verbatim. - Cookie headers (
Cookie:/Set-Cookie:) — previously unhandled entirely. Session, auth, and CSRF tokens passed through in cleartext.
Good:
- Escape-aware JSON string matching correctly handles embedded escaped quotes
name=valuerequirement on bare cookie regex avoids false positives on prose- Test coverage: bare form, JSON form, escaped quotes, mixed case, prose, combined request dump, and
code_file=Truepassthrough
No issues — approving.
teknium1
left a comment
There was a problem hiding this comment.
Thanks for covering the serialized-header and cookie redaction gaps; both remain on current main (agent/redact.py:604-610), and request dumps serialize then redact their payload at agent/agent_runtime_helpers.py:1502-1505.
Problems
agent/redact.py:165uses\S+=[^\r\n]+for raw Cookie values. This consumes quote delimiters and subsequent same-line text. An inlinecurl -H "Cookie: sid=secret" https://…would be reduced to an unterminated command and lose its URL. Current main fixed the identical Authorization quote-eating class inbbe1bf4045427b2dca7d8e4acbe042969cd3ad6aby excluding quote characters from the credential match.
Suggested changes
- Bound the raw Cookie payload at quote delimiters and add quoted single/double
curl -Hregressions that retain the quote and URL.
This is an automated hermes-sweeper review.
| # is preserved. A ``name=value`` pair is required so plain prose ("the cookie: | ||
| # …") is left untouched. | ||
| _COOKIE_HEADER_RE = re.compile( | ||
| r"((?:Set-)?Cookie:\s*)(\S+=[^\r\n]+)", |
There was a problem hiding this comment.
[^\r\n]+ consumes closing shell quotes and trailing same-line command text. Bound this raw Cookie payload before '/" and add quoted curl -H regressions; current main made that exact quote-preservation fix for Authorization in bbe1bf4.
|
suggesting changes The new JSON header substitutions can turn valid serialized headers into invalid JSON. They pass the regex-captured escape stream directly to This reaches the request-dump path because Security evidence:
Not checked:
Signed: GPT-5.6-sol-xhigh in Codex |
1fd8ca9 to
5530ae3
Compare
|
Rebased onto current The reported JSON invariant is now fixed by decoding captured header values before masking and JSON-encoding them again afterward, so masking cannot split an escape pair and the request-dump The replay also adds regressions for the adjacent boundaries exercised by this redaction path:
Validation on the rebased head:
The remaining scope is intentional: the persisted sink emits canonical keys via Python |
5530ae3 to
d458eb1
Compare
|
Refreshed to current Validation on macOS: the current redaction suite (116 tests), two new syntax/security invariants, and the preserved prior 170-test suite all pass (288 total). Both new invariants fail on upstream. I also exercised the real The new committed test file keeps two invariants: parseable credential-free JSON headers and bounded raw/curl headers that preserve quoting, URLs and the next line. Scope remains header redaction; general JSON-field handling in #69196 and the cookie/dump-specific proposals remain separate. AI-assisted implementation and self-review. |
shapes of the same leak class still reach the on-disk request-dump sink:
- JSON-serialized secret headers ("x-api-key": "<opaque>") — opaque
custom/local-backend keys that have no vendor prefix for _PREFIX_RE.
- Cookie:/Set-Cookie: headers (session/auth/CSRF tokens), previously
unhandled entirely.
Both classes are closed in raw and JSON-serialized form. The JSON value
regexes are escape-aware (escaped quotes can't truncate the match) and
the JSON cookie matcher uses a single unambiguous group (no ReDoS).
Adds regression tests for each form incl. the request-dump sink.
d458eb1 to
af746e3
Compare
Opaque JSON API-key headers and Cookie/Set-Cookie values remain visible in diagnostic request dumps on main. This follow-up to #50423 masks those headers while preserving parseable JSON, shell quote delimiters, the curl destination, and subsequent header lines.
JSON values are decoded, masked, and JSON-encoded so escaped quotes and backslashes cannot be split at a mask boundary. Raw and curl header handling uses bounded contexts, including continued commands and truncated diagnostic lines. JSON and Cookie source fixtures retain the existing code_file exemption. The current shared SECRET_HEADER_NAME_LIST, profile/vault handling, escaped-field handling, and Python-repr redaction are retained. Secret-bearing file reads also retain the current non-reusable mask sentinel.
Validation on macOS, Python 3.14, rebased on f86276d:
Overlapping proposals #50607/#83002 cover cookie subsets, #69196 covers general JSON fields, and #51049 covers dump-specific fields; none has merged at verification. This PR remains limited to the existing header-redaction topic.
AI-assisted implementation and self-review. GitHub CI has required maintainer approval; local validation is reported separately.