Repository navigation
fix(redact): Python repr dict secrets no longer leak in tracebacks and pytest output (salvage #71370) - #92586
Conversation
૮ >ﻌ< ა ci reviewran on 7af2fc8 — fix(redact): repr pass leaves already-masked values alone
|
Solid addition to the redaction stack. The design choices are well-reasoned and tested against the actual failure modes: full Two points: 1. Suffix matching has predictable collateral on LLM-shaped fields — 2. Unrelated file in a focused security PR — Minor observations, no action needed:
The parametrized matrix across command shapes ( |
…ixes Port from OpenHands/software-agent-sdk#4508: their dict-entry secret redaction was uppercase-only and leaked mixed-case keys (UserPassword, sessionToken). Apply the same case-insensitive treatment to the Python mapping-repr pass: a casefolded credential suffix (apikey/token/secret/ password/passwd/credential) now qualifies a key, while metadata names (TOKEN_COUNT, password_policy, tokenizer) stay untouched.
The Python-repr pass ran after the MCP probe header scrub and collapsed 'Authorization': 'Digest ***' to '***', erasing the scheme word that scrub deliberately keeps (tests/hermes_cli/test_mcp_probe_redaction.py went red on rebase). Skip values that already carry a mask marker.
2af31a0 to
7af2fc8
Compare
Summary
Opaque credentials in Python mapping
reproutput —{'BRAVE_API_KEY': 'opaque-value'}in tracebacks, pytest assertion introspection (E kwargs=...), and final exception lines — are now masked. The double-quoted JSON pass never covered single-quoted repr fields, so any dict repr surfaced by terminal/process output leaked opaque secrets verbatim.Salvage of #71370 by @aerbaser (cherry-picked, authorship preserved), rebased onto current
mainand widened one notch: the key class is now case-insensitive for credential-suffixed names (UserPassword,sessionToken,clientApiKey) — the same uppercase-only gap OpenHands fixed in software-agent-sdk#4508.Changes
agent/redact.py: new_redact_python_repr_fields()pass for single/double-quoted mapping-repr fields (str + bytes values, full mask so escaped atoms stay parseable); narrowly scoped_redact_python_diagnostic_repr_fields()applied to pytestElines and finalError:/Exception:lines in otherwise source-preserving (code_file=True) terminal output; env-lookup values (os.getenv(...)) preserved like the ENV/JSON/YAML passes.agent/redact.py: mixed-case credential-suffix widening (_PYTHON_REPR_CREDENTIAL_SUFFIXES, casefolded, suffix-only soTOKEN_COUNT/password_policy/tokenizernever match)._command_reads_env_filegate inredact_terminal_outputand adds the diagnostic pass on top.tests/agent/test_redact.py: contributor's repr/diagnostic tests + new mixed-case positive/negative parametrizations.Validation
{'api_key': 's3cr3t…'}'api_key': '***'{'UserPassword': 'p@ss…'}'UserPassword': '***'E kwargs={'env': {'BRAVE_API_KEY': …}}(pytest)CONFIG = {...}viacat config.py{'TOKEN_COUNT': '12345'},Secretary of the Treasurytests/agent/test_redact.py: 139 passed.Closes #71370.
Infographic