# NousResearch/hermes-agent · Redact false positives on code files fix

## Open now

- Nothing open on GitHub.

A bug was identified where ENV/JSON regex patterns in secret redaction caused false positives on source code files. These members address adding a code_file parameter and restricting redaction logic to avoid corrupting code output.

## TL;DR

- 4 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #19715. Verify it addresses your case.
- **Recommended:** read PR #19715 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-19715`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.50`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #15934: bug(redact): ENV/JSON regex patterns cause false positives on source code files

## Prior & competing PRs

- **#19715: fix(redact): add code_file param to skip false-positive ENV/JSON patterns**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/redact.py`, `tools/file_tools.py`
  - fix hunks:
  - `agent/redact.py`

    ```diff
    @@ -305,13 +305,18 @@ def _redact_form_body(text: str) -> str:
         return _redact_query_string(text.strip())
     
     
    -def redact_sensitive_text(text: str, *, force: bool = False) -> str:
    +def redact_sensitive_text(text: str, *, force: bool = False, code_file: bool = False) -> str:
         """Apply all redaction patterns to a block of text.
     
         Safe to call on any string -- non-matching text passes through unchanged.
         Disabled by default — enable via security.redact_secrets: true in config.yaml.
         Set force=True for safety boundaries that must never return raw secrets
         regardless of the user's global logging redaction preference.
    +
    +    Set code_file=True to skip the ENV-assignment and JSON-field regex
    +    patterns when the text is known to be source code (e.g. MAX_TOKENS=***
    +    constants, "apiKey": "test" fixtures). Prefix patterns, auth headers,
    +    private keys, DB connstrings, JWTs, and URL secrets are still redacted.
         """
         if text is None:
             return None
    ```

    ```diff
    @@ -325,17 +330,18 @@ def redact_sensitive_text(text: str, *, force: bool = False) -> str:
         # Known prefixes (sk-, ghp_, etc.)
         text = _PREFIX_RE.sub(lambda m: _mask_token(m.group(1)), text)
     
    -    # ENV assignments: OPENAI_API_KEY=[redacted:secret-assignment]
    -    def _redact_env(m):
    -        name, quote, value = m.group(1), m.group(2), m.group(3)
    -        return f"{name}={quote}{_mask_token(value)}{quote}"
    -    text = _ENV_ASSIGN_RE.sub(_redact_env, text)
    -
    -    # JSON fields: "apiKey": "value"
    -    def _redact_json(m):
    -        key, value = m.group(1), m.group(2)
    -        return f'{key}: "{_mask_token(value)}"'
    -    text = _JSON_FIELD_RE.sub(_redact_json, text)
    +    # ENV assignments: OPENAI_API_KEY=***  (skip for code files — false positives)
    +    if not code_file:
    +        def _redact_env(m):
    +            name, quote, value = m.group(1), m.group(2), m.group(3)
    +            return f"{name}={quote}{_mask_token(value)}{quote}"
    +        text = _ENV_ASSIGN_RE.sub(_redact_env, text)
    +
    +        # JSON fields: "apiKey": "***"  (skip for code files — false positives)
    +        def _redact_json(m):
    +            key, value = m.group(1), m.group(2)
    +            return f'{key}: "{_mask_token(value)}"'
    +        text = _JSON_FIELD_RE.sub(_redact_json, text)
     
         # Authorization headers
         text = _AUTH_HEADER_RE.sub(
    ```
  - `tools/file_tools.py`

    ```diff
    @@ -570,7 +570,7 @@ def read_file_tool(path: str, offset: int = 1, limit: int = 500, task_id: str =
     
             # ── Redact secrets (after guard check to skip oversized content) ──
             if result.content:
    -            result.content = redact_sensitive_text(result.content)
    +            result.content = redact_sensitive_text(result.content, code_file=True)
                 result_dict["content"] = result.content
     
             # Large-file hint: if the file is big and the caller didn't ask
    ```

    ```diff
    @@ -993,7 +993,7 @@ def search_tool(pattern: str, target: str = "content", path: str = ".",
             if hasattr(result, 'matches'):
                 for m in result.matches:
                     if hasattr(m, 'content') and m.content:
    -                    m.content = redact_sensitive_text(m.content)
    +                    m.content = redact_sensitive_text(m.content, code_file=True)
             result_dict = result.to_dict()
     
             if count >= 3:
    ```
- **#15923: fix(redact): skip ENV/JSON patterns on code files to avoid false positives**. closed without merge
  - maintainer direction: category `silent_close`; implication `active`
- **#16127: fix(redact): add code_file param to skip false-positive ENV/JSON patterns**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#19715`

## Fix status

- Merged to main in PR #19715 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-05-04`.
