Skip to content

[Bug]: Redaction incorrectly masks lowercase Python variable assignments #4367

@InB4DevOps

Description

@InB4DevOps

Bug Report

Bug Description

The redaction regex in agent/redact.py incorrectly redacted values of lowercase Python variable assignments, treating them as environment variables containing secrets.

For example:

before_tokens = self._estimate_current_context_tokens()

Would be incorrectly transformed to:

before_tokens = ***

This happened because the _ENV_ASSIGN_RE regex used the re.IGNORECASE flag, which caused it to match lowercase Python variable names (like before_tokens, api_key, my_token) in addition to uppercase environment variables (like API_KEY, OPENAI_API_KEY).

Steps to Reproduce

  1. Enable redaction in config (security.redact_secrets = true)
  2. Run any Hermes command that outputs Python code snippets in logs
  3. Observe that lowercase variable assignments like before_tokens = ... have their values redacted

Expected Behavior

Only ALL-uppercase environment variable assignments should be redacted:

  • API_KEY=secret123API_KEY=***
  • OPENAI_API_KEY=sk-abc...OPENAI_API_KEY=***

Lowercase Python variable assignments should pass through unchanged:

  • before_tokens = self._estimate...()before_tokens = self._estimate...()
  • api_key = secretapi_key = secret

Actual Behavior

Both environment variables AND lowercase Python variables were being redacted:

  • API_KEY=secret123API_KEY=***
  • before_tokens = self._estimate...()before_tokens = ***
  • api_key = secretapi_key = ***

Affected Component

  • Agent Core (conversation loop, context compression, memory)

Operating System

Ubuntu 24.04

Python Version

3.13.5

Hermes Version

0.6

Root Cause Analysis

The bug is in agent/redact.py line 57:

_ENV_ASSIGN_RE = re.compile(
    rf"([A-Z_]*{_SECRET_ENV_NAMES}[A-Z_]*)\s*=\s*(['\"]?)(\S+)\2",
    re.IGNORECASE,  # ← This flag caused lowercase matches
)

The re.IGNORECASE flag caused the [A-Z_] character class to match lowercase letters as well. Additionally, the regex lacked a proper anchor at the start, allowing it to match mid-word.

Proposed Fix

  1. Remove re.IGNORECASE flag
  2. Add (?:(?:^|\s)) anchor before the variable name to match from start of string or whitespace
  3. Add regression test test_lowercase_python_vars_not_redacted
_SECRET_ENV_NAMES = r"(?:API_?KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)"
_ENV_ASSIGN_RE = re.compile(
    rf"(?:(?:^|\s))([A-Z_]+{_SECRET_ENV_NAMES}[A-Z_]*)\s*=\s*(['\"]?)(\S+)\2",
)

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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