security-guidance plugin: eval_injection rule falsely flags ast.literal_eval()
Describe the bug
The eval_injection rule in the security-guidance plugin (plugins/security-guidance/hooks/security_reminder_hook.py) uses substring matching for "eval(" which catches ast.literal_eval() — a safe Python stdlib function that only parses literal values (strings, numbers, tuples, lists, dicts, booleans, None). It does NOT execute arbitrary code.
This causes legitimate uses of ast.literal_eval() to be blocked during Edit/Write/MultiEdit operations with:
⚠️ Security Warning: eval() executes arbitrary code and is a major security risk.
Consider using JSON.parse() for data parsing or alternative design patterns that
don't require code evaluation. Only use eval() if you truly need to evaluate
arbitrary code.
Steps to reproduce
- Install
security-guidance@claude-plugins-official - Attempt to edit a
.pyfile containingast.literal_eval() - The hook blocks the edit
Expected behavior
ast.literal_eval() should not be flagged. It's a well-known safe alternative to eval() specifically designed for parsing Python literals without code execution.
Suggested fix
Add an exclude_substrings field to the pattern schema so specific safe patterns can be whitelisted. For the eval_injection rule:
{
"ruleName": "eval_injection",
"substrings": ["eval("],
"exclude_substrings": ["ast.literal_eval"],
"reminder": "..."
}
And update check_patterns to check exclusions before returning a match:
if substring in content:
excluded = False
for exclude_sub in pattern.get("exclude_substrings", []):
if exclude_sub in content:
excluded = True
break
if not excluded:
return pattern["ruleName"], pattern["reminder"]
This is backward-compatible (patterns without exclude_substrings work as before) and extensible to other false-positive cases.
Related
- Issue #46720 reports the same class of substring-matching false positive for
exec(in docs/markdown files. Anexclude_substringsmechanism would also help there (e.g. exclude markdown code blocks from triggering the hook).
5 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Three working workarounds for anyone blocked by this right now, in order from least to most invasive. The proposed
exclude_substringsfix is the right long-term answer — these are stopgaps until it lands.1. Just retry the Edit (zero work, but undocumented)
Reading the hook source (
security_reminder_hook.py, end ofmain()):The
(file_path, rule_name)warning key is added to session state before the block, and only the first occurrence blocks — the second attempt against the same file passes through with no warning and no block. So if you hit this in the middle of work: re-issue the same Edit and it goes through. Fragile (silent in subsequent sessions, also masks legitimate first-occurrence flags), but it gets you unstuck without touching files.2. Local patch the rule (survives until next plugin update)
The patterns are inline in the same script. Two options:
a. Apply the
exclude_substringspatch you outlined directly in the local copy at:b. Or remove the rule entirely if you don't want any
eval(warnings at all. Find the dict starting"ruleName": "eval_injection"and drop it from the patterns list.Either gets reverted on the next
claude plugin update security-guidance, so it's not durable, but it works today. Keep a one-line cron or git diff to detect when the upstream lands the fix and you can drop the local patch.3. Use Bash +
sedfor the one-off edit (sidesteps the hook entirely)The matcher is
Edit|Write|MultiEdit, soBashinvocations are not checked. For a single mechanical change like adding a newast.literal_eval(...)call,sed -i(or a here-doc +cat >) goes through unimpeded. Less ergonomic, but useful when you'd rather not patch plugin internals.---
On the substring approach in general — agreed that
exclude_substringsis the right primitive. While we're at it, the same matcher also flags any markdown/doc that quoteseval(for explanatory purposes (#46720), so the exclusion mechanism would want to also handle "inside a code-fence in a.mdfile" — possibly via afile_extensions_exclude: [".md", ".rst"]companion field on each rule. That's two false-positive classes covered by one schema addition.Thank you for this @yurukusa , was struggling with data science work for the past 2 weeks because of this.
Audit shows the
eval_injectionregex now has a negative lookbehind that excludesast.literal_eval. Please retest on the latest plugin (anthropics/claude-plugins-official). Closing — please reopen if you still get the false positive.This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.