Skip to content

fix: make dict-entry secret redaction case-insensitive - #4508

Merged
enyst merged 1 commit into
OpenHands:mainfrom
chintan-diwakar:fix/redact-case-insensitive-dict-keys
Aug 16, 2026
Merged

enyst merged 1 commit into
OpenHands:mainfrom
chintan-diwakar:fix/redact-case-insensitive-dict-keys

Conversation

@chintan-diwakar

@chintan-diwakar chintan-diwakar commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

HUMAN:

I reviewed the two-flag regex diff and the failing-then-passing pytest output for the new regression tests before submitting.


AGENT:

Why

The two dictionary-entry substitutions in redact_text_secrets (openhands-sdk/openhands/sdk/utils/redact.py) only matched uppercase key names ([A-Z_]*(?:KEY|SECRET|TOKEN|PASSWORD)[A-Z_]*), so text like {'api_key': 's3cr3t'} or 'UserPassword': 'p@ssw0rd' passed through unredacted. The same module's is_secret_key matches case-insensitively, and the function's docstring does not restrict the key categories to uppercase. redact_text_secrets runs on ACP stdout/stderr lines and error details before they reach logs, so lowercase secret keys in process output leaked.

Summary

  • Add flags=re.IGNORECASE to both dict-entry substitutions in redact_text_secrets; quote handling, value boundaries, URL/header/API-key-literal behavior, and uppercase matching are untouched
  • Add TestRedactTextSecretsDictKeys regression tests: the issue's exact reproduction (verified failing before the fix, passing after), uppercase keys still redacted, non-sensitive entries unchanged

Issue Number

Fixes #4505

How to Test

uv run pytest tests/sdk/utils/test_redact.py -q

38 tests pass on this branch. Before the fix, test_redacts_lowercase_and_mixed_case_dict_keys fails with the secrets left in the output, reproducing the issue exactly.

End-to-end check through the ACP logging path (acp_agent.py passes raw output lines through redact_text_secrets before logging). Running the same line through the public API on main vs this branch:

$ python -c "from openhands.sdk.utils.redact import redact_text_secrets; print(redact_text_secrets(\"auth failed for {'api_key': 's3cr3t-value', \\\"token\\\": \\\"tok-XYZ\\\", 'normal': 'keep-me'}\"))"

# on main:
auth failed for {'api_key': 's3cr3t-value', "token": "tok-XYZ", 'normal': 'keep-me'}

# on this branch:
auth failed for {'api_key': '<redacted>', "token": "<redacted>", 'normal': 'keep-me'}

Also ran tests/sdk/utils/test_command.py (a redact_text_secrets caller): 12 passed. ruff check and ruff format --check clean on both changed files.

Video/Screenshots

Not a GUI change; the before/after log output above shows the behavior change.

Design Doc

Not needed for a two-flag fix.

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

The module docstring lists OpenHands/runtime-api as carrying a partial copy of this file; that copy may want the same flag if it shares these patterns.

🤖 Generated with Claude Code

@all-hands-bot

Copy link
Copy Markdown
Collaborator

👋 This PR needs a couple of things fixed before OpenHands can review it:

  • the PR description's HUMAN: section needs at least 20 characters describing what you tested, not just the template placeholder

Push an update once this is addressed and this check re-runs automatically.

This is an automated check - no AI was used to generate this comment.

@all-hands-bot

Copy link
Copy Markdown
Collaborator

🚦 CI is currently failing on this PR's latest commit.

Please fix the failing checks before OpenHands reviews it - this is re-checked automatically once you push a new commit. (A maintainer can also request @all-hands-bot as a reviewer to have it reviewed regardless of CI status.)

This is an automated check - no AI was used to generate this comment.

The two dictionary-entry patterns in redact_text_secrets only matched
uppercase key names, so text like {'api_key': 's3cr3t'} passed through
unredacted while the module's is_secret_key helper matches
case-insensitively. Add re.IGNORECASE to both substitutions so
lowercase and mixed-case keys containing key/secret/token/password are
redacted, matching the documented behavior.

Fixes OpenHands#4505

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chintan-diwakar
chintan-diwakar force-pushed the fix/redact-case-insensitive-dict-keys branch from ce1fc2a to f798777 Compare August 16, 2026 14:07
@all-hands-bot

Copy link
Copy Markdown
Collaborator

🚦 CI is currently failing on this PR's latest commit.

Please fix the failing checks before OpenHands reviews it - this is re-checked automatically once you push a new commit. (A maintainer can also request @all-hands-bot as a reviewer to have it reviewed regardless of CI status.)

This is an automated check - no AI was used to generate this comment.

@enyst enyst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@enyst
enyst merged commit 007721b into OpenHands:main Aug 16, 2026
28 of 29 checks passed
RFingAdam pushed a commit to RFingAdam/hermes-agent that referenced this pull request Aug 26, 2026
…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.

(cherry picked from commit bbcaad4)
teknium1 added a commit to NousResearch/hermes-agent that referenced this pull request Sep 14, 2026
…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.
teknium1 added a commit to NousResearch/hermes-agent that referenced this pull request Sep 14, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: redact_text_secrets misses lowercase and mixed-case secret keys

3 participants