Skip to content

feat(security-guidance): secret detection slice (#398, child of #390)#404

Merged
Lexus2016 merged 2 commits into
mainfrom
evolution/issue-398-secret-detection
Jun 21, 2026
Merged

feat(security-guidance): secret detection slice (#398, child of #390)#404
Lexus2016 merged 2 commits into
mainfrom
evolution/issue-398-secret-detection

Conversation

@Lexus2016

Copy link
Copy Markdown
Owner

Closes #398
Advances #390 (parent — first slice).

What

First shippable slice of the security code-review plugin: detect hardcoded credentials in write_file / patch / skill_manage content, surfacing a warning (or blocking, in block mode) before the model moves on.

Files

  • plugins/security-guidance/secrets.py (new, Hermes-side) — kept OUT of patterns.py, which is byte-for-byte the Anthropic fork (provenance preserved) and has a RuleId-sync assert.
    • Regex rules: AWS access key, AWS secret, GitHub token + fine-grained PAT, Slack token + webhook, Google API key, Stripe live key, npm token, PEM private key, JWT, generic api-key/secret assignment.
    • Conservative Shannon-entropy backstop: high-entropy value assigned to a secret-named key, fired only when no known-format rule matched (no duplicate warnings).
    • Placeholder/example exclusion (example/redacted/your-/xxxx/<...>/…) for a low false-positive rate.
  • __init__.pyfrom . import secrets; one line in _scan_args so findings flow through the existing warn-mode (transform_tool_result) and block-mode (pre_tool_call) paths.

Out of scope (tracked in parent #390)

Injection-pattern detectors (SQL/command/path/SSRF), pre-commit diff-review mode, static-analyzer integration.

Tests

tests/plugins/test_security_guidance_secrets.py22 tests: AWS / SSH-PEM / Slack / GitHub / Google / Stripe / npm / JWT / generic detection, entropy backstop (+ low-entropy & known-format suppression), false-positive sanity (benign code, placeholders, examples, oversized input), and warn+block hook integration. Token fixtures are assembled from parts so neither GitGuardian nor the repo's secret scanners match the test file. Full plugin suite: 49 passed.

Success criteria (#398)

  • regex + entropy checks for common secrets in patterns-adjacent module
  • hooked into the existing write_file/patch/skill_manage scan path
  • configurable warn (default) vs block via SECURITY_GUIDANCE_BLOCK
  • tests for AWS/SSH/slack-token detection + false-positive sanity

First shippable slice of the security code-review plugin: detect hardcoded
credentials in write_file / patch / skill_manage content.

- New Hermes-side module plugins/security-guidance/secrets.py (kept out of
  patterns.py, which is byte-for-byte the Anthropic fork):
  * regex rules for well-known formats — AWS access key, AWS secret,
    GitHub token + fine-grained PAT, Slack token + webhook, Google API
    key, Stripe live key, npm token, PEM private key, JWT, generic
    api-key/secret assignments.
  * conservative Shannon-entropy backstop: a high-entropy value assigned
    to a secret-named key, fired only when no known-format rule matched
    (no duplicate warnings).
  * placeholder/example exclusion (example/redacted/your-/xxxx/<...>/...)
    to keep the false-positive rate low.
- Wired into _scan_args so findings flow through the existing warn-mode
  (transform_tool_result) and block-mode (pre_tool_call, env
  SECURITY_GUIDANCE_BLOCK) paths with no special handling.

Out of scope for this slice (tracked in parent #390): injection-pattern
detectors, pre-commit diff-review mode, static-analyzer integration.

Tests: tests/plugins/test_security_guidance_secrets.py — 22 tests
(AWS/SSH-PEM/Slack/GitHub/Google/Stripe/npm/JWT/generic detection,
entropy backstop, false-positive sanity, warn+block hook integration).
Token fixtures assembled from parts so secret scanners don't match the
test file. Full plugin suite: 49 passed.
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: evolution/issue-398-secret-detection vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11322 on HEAD, 11314 on base (🆕 +8)

🆕 New issues (4):

Rule Count
unresolved-attribute 2
invalid-argument-type 1
unresolved-import 1
First entries
tests/plugins/test_security_guidance_secrets.py:55: [unresolved-attribute] unresolved-attribute: Attribute `exec_module` is not defined on `None` in union `Loader | None`
tests/plugins/test_security_guidance_secrets.py:51: [invalid-argument-type] invalid-argument-type: Argument to function `module_from_spec` is incorrect: Expected `ModuleSpec`, found `ModuleSpec | None`
tests/plugins/test_security_guidance_secrets.py:21: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
tests/plugins/test_security_guidance_secrets.py:55: [unresolved-attribute] unresolved-attribute: Attribute `loader` is not defined on `None` in union `ModuleSpec | None`

✅ Fixed issues: none

Unchanged: 5942 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

…sion for prefix rules (#398)

- Split placeholder exclusion: fixed-prefix rules (AKIA/ghp_/etc) now use
  EXAMPLE-only exclusion so a real key containing 'xxxx'/'00000000' as a
  substring is never silently dropped (fail-open fix, review nit #1).
  Assignment-style rule keeps the broad placeholder set.
- Docstring notes the conservative entropy threshold won't catch low-entropy
  passphrases (nit #3); Stripe live-only comment (nit #2); _MAX_SCAN_BYTES
  cross-ref to __init__.py (nit #4).
- Add regression test: prefix key with '00000000' substring still detected.
@Lexus2016 Lexus2016 merged commit 70ca861 into main Jun 21, 2026
39 checks passed
@Lexus2016 Lexus2016 deleted the evolution/issue-398-secret-detection branch June 21, 2026 07:45
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.

[CHILD/#390] Security code-review plugin — secret detection slice

1 participant