fix(debug): only treat a masked scheme as one before a token-shaped key

Review finding (BR1 r3 2c Medium / 2ab Low): the `***` arm added to
_BARE_HEADER_RE treated ANY same-line word after an already-masked
value as the secret, so benign prose was eaten and every re-scrub ate
one more word (`x-api-key: *** see docs for details` -> `... docs for
details` -> `... details`; same for `Authorization: *** then prose`,
`X-Api-Key: *** (set in env)`). The scrub was not a fixed point.

Require the follow-on value to look like a credential (>=8 token chars,
optional `=` padding, then a token boundary) before `***` counts as a
masked scheme. The floor is 8, not 16, so 15-char keys still redact.
The 336-case header sweep stays at 0 leaks / 0 unstable, the 18
`name: <scheme> <key>` cases are still redacted, and the benign lines
are stable over three passes.
This commit is contained in:
kshitijk4poor
2026-10-03 20:45:44 +05:30
committed by kshitij
parent 5381678d03
commit eb4bba0b2d
2 changed files with 6 additions and 3 deletions

View File

@@ -54,9 +54,9 @@ _QUOTED_HEADER_RE = re.compile(
_BARE_HEADER_RE = re.compile(
rf"(?P<prefix>\b(?:{_HEADER_NAME_PATTERN})\b\s*[:=]\s*)"
# agent.redact masks the scheme of ``x-api-key: Basic <key>`` to ``***`` and
# keeps the key, so ``***`` before a same-line value (not another secret
# header) is a scheme too, and the key after it is the value.
r"(?P<value>(?>(?:(?:Bearer|Basic|Digest)\s+|\*\*\*[ \t]+(?=[^\s,}\]])"
# keeps the key, so ``***`` before a same-line token-shaped value (not prose
# and not another secret header) is a scheme too, and the key is the value.
r"(?P<value>(?>(?:(?:Bearer|Basic|Digest)\s+|\*\*\*[ \t]+(?=[A-Za-z0-9._~+/-]{8,}=*(?![A-Za-z0-9._~+/=-]))"
rf"(?!(?:{_HEADER_NAME_PATTERN})\b\s*[:=]))?)(?!\[REDACTED\])[^\s,}}\]]+)",
re.IGNORECASE,
)

View File

@@ -189,6 +189,9 @@ def test_redacted_support_egress_scrubs_structured_values_and_errors(
assert "[REDACTED]]" not in failure["error"]
assert failure["error"].endswith(" --header X-API-Key Basic [REDACTED]")
assert real_redact(failure["error"]) == failure["error"]
# Prose after an already-masked value is not a key: kept, and a fixed point.
benign = real_redact("x-api-key: *** see docs")
assert benign.endswith(" see docs") and real_redact(benign) == benign
def test_share_nous_linkless_success_is_a_failure(monkeypatch):