Development velocity has moved faster than the machinery built to review it. An engineer working with a coding agent can touch a dozen files, refactor across them, and commit inside an afternoon. The gates around that work mostly stayed where they were: static analysis in CI, dependency scanners on a schedule, and a human reading the diff once it reaches a pull request. Those gates assume that writing code is the slow step.
That assumption no longer holds, and the cost shows up as delay. A vulnerable query gets written, committed, and pushed before anything examines it, and the tool that eventually flags it is describing work the author finished hours earlier and has stopped thinking about. The gates are not wrong. There are simply more diffs arriving than they were built to absorb, and the later a finding lands, the more expensive it is to act on.
Anthropic’s security-guidance plugin moves the first check into the session itself. Claude writes code, the plugin reviews the change, and findings come back to Claude in the same conversation. There is nothing to invoke and no command to remember.
I spent an evening setting it up in a small repository and then trying to get each of its three layers to fire on code written to trip them. This is what that took, and how to tell that each layer is actually running rather than merely installed.
What the plugin does
The plugin is built from Claude Code lifecycle hooks. It registers SessionStart to bootstrap a Python environment, UserPromptSubmit to capture a git baseline for the turn, PostToolUse on the edit tools for the pattern check, Stop for the end-of-turn review, and PostToolUse on Bash filtered to git commit and git push for the deep review. If those event names are new to you, the hooks reference describes what each one fires on.
Those registrations give you three layers at increasing depth and cost.
Layer 1 is a string and regex match with no model call, so it is free and instant. It covers dynamic execution such as eval( and os.system, unsafe deserialization such as pickle, DOM injection such as .innerHTML = and dangerouslySetInnerHTML, and edits under .github/workflows/, which can quietly grant repository permissions. Those are the built-ins you get before writing anything. Your own rules from security-patterns.json run in this same pass, covered further down.
Layer 2 diffs the working tree at the end of a turn and sends the result to a separate Claude call with a security-only prompt. It covers what a string match cannot: injection, server-side request forgery, weak cryptography, authorization bypass. It runs in the background, so Claude’s reply is not delayed, and it covers up to 30 changed files per turn.
Layer 3 fires when Claude runs git commit or git push through its Bash tool. This reviewer reads surrounding code, including callers and sanitizers, before deciding whether a finding is real. It is capped at 20 reviews per rolling hour.
One point is worth saying to your team early, because it is the first thing they will assume wrongly. None of these layers stops anything. They find problems and hand them to Claude, which fixes them in the conversation. Nothing gets blocked. If you want a hard stop, you build it yourself with a PreToolUse hook or a check in CI.
Prerequisites
- Claude Code 2.1.144 or later (Scroll to the end if you’re on OpenRouter)
- Python 3.10 or later, and a git repository
A repository worth attacking
None of the checks below mean anything against an empty directory, so the first thing I built was a small Python service with a few files: a data layer , a couple of route stubs, and a front-end file so the JavaScript patterns had somewhere to land. The baseline is deliberately clean, which makes the contrast visible when Claude adds something unsafe on request.
Then git init and a first commit. Layer 2 diffs the working tree and Layer 3 only fires on git commit or git push, so without a repository two of the three checks quietly do nothing.
Installing security-guidance plugin
1.Run this inside a Claude Code session to install the official plugin from the Anthropic:
/plugin install security-guidance@claude-plugins-official
2.The installer asks for a scope. Choose “Install for all collaborators on this repository”, which writes .claude/settings.json for you with the plugin enabled.
3.Then apply it to the open session:
/reload-plugins
- Confirm the file
settings.jsonlanded under the.claudefolder in your project root.
Note: If the marketplace is not registered on the machine, add it first with /plugin marketplace add anthropics/claude-plugins-official and retry.
What ends up in the repository
The installer writes one of the three files. You write the other two, because the plugin has no opinion about your codebase and never generates them.
The full working example, including the demo repository these snippets come from, is on [GitHub]
They are configuration, they belong next to the code they protect, and versioning them means a rule change shows up in review like any other change.
Your threat model, in plain English
The two model-backed reviews load .claude/claude-security-guidance.md as extra context alongside the built-in vulnerability checklist. There is no DSL. Write the rules the way you would explain them to a new hire.
This is the file that carries knowledge a generic scanner cannot have. Nothing about org_id is universal. It is your schema, and the reviewer only knows about it because you wrote it down.
Custom patterns for the free layer
Anthropic’s security plugin includes built-in detection patterns in patterns.py. You can locate the file with:
find ~/.claude/plugins -path '*security-guidance/hooks/patterns.py'
You can add your own custom patterns in .claude/security-patterns.json. These feed the free Layer 1 checks, so they run instantly with no additional model cost.
The plugin also supports .yaml, .yml and .json using the same schema. YAML requires PyYAML to be installed separately, while JSON works on any standard Python installation.
What each layer can see
The layering is worth understanding before you decide how much of it to pay for.
| Layer | Sees | Strength | Limitation |
|---|---|---|---|
| Layer 1 | Single edit only | Free, instant pattern matching | No project context or data flow awareness |
| Layer 2 | All changes in the current turn | Tracks data flow across the diff | Limited to current-turn changes |
| Layer 3 | Diff plus related files | Uses project context to reduce false positives |
Proving each layer fires
Installing the plugin and reading the docs tells you what should happen. It does not tell you what is happening on your machine.
Start a fresh session from the repo root and run /hooks, which should show registrations against SessionStart, UserPromptSubmit, PostToolUse, and Stop. That screen makes a good opening slide for a team walkthrough, because it shows there is nothing hidden in the design.
Then make each layer fire on purpose. The plugin keeps its own log at ~/.claude/security/log.txt, and that is the thing to read rather than the session transcript. Claude sometimes adds its own security comments to code unprompted, which is easy to mistake for the plugin having spoken.
Keep a second terminal open on the log before prompting claude-code:
tail -f ~/.claude/security/log.txt
Check 1: the built-in pattern layer
Ask for something the built-in list covers.
In app/routes.py, add a function run_report(expr) that evaluates the expr string the caller passes in and returns the result. Keep it to three lines.
Claude writes eval(expr). The warning appears in the transcript with no perceptible delay. Next, screen shows the hook event and pattern matched.
Check 2: your own pattern rule
Same free layer, your vocabulary. This one exercises the paths glob, which is the part most likely to be silently wrong.
In app/db.py add a function list_invoices() that returns Invoice.objects.all().
The warning text should be the reminder string you wrote, not a generic one.
Note: A rule that never appears here, with no error anywhere, is almost always a paths glob missing its **/ prefix.
Check 3: the end-of-turn model review
Now ask for something no string match will catch cleanly.
Add a function search_users(term) to app/db.py that runs a LIKE query against the users table. Build the SQL as an f-string so it is easy to read.
Claude replies without delay. A few seconds later the review returns in the background. Claude is re-prompted with the finding. If it acknowledges the finding but leaves the code as it is, prompt “apply the security review’s recommendation” and it will rewrite the query with parameter binding.
Check 4: the commit review
Let Claude make the commit itself, since this layer only sees commits that go through its Bash tool.
Commit everything we just changed with a sensible message.
The commit completes, then the deeper review runs in the background and reports separately after a few minutes:
This reviewer reads related files before deciding, so it takes longer than Layer 2 and may run several model turns. If its findings duplicate what the end-of-turn review already reported, Claude is not re-prompted, so a clean commit can produce no visible output at all. That silence is documented behaviour rather than a failure.
Worth noticing while this is on screen: the commit already exists by the time the finding arrives. Any fix becomes a second commit. “Review on commit” sounds like a gate and is not one.
Limits worth stating up front
- Manual commits, shell escapes, or commits made outside Claude are not reviewed. A CI security check is still recommended.
- Findings are suggestions, not guarantees. The model can miss vulnerabilities, generate false positives and its results may vary across codebases, languages and model versions.
- This plugin complements, but does not replace, static analysis, dependency scanning, pull request reviews, or human review.
- The plugin is an early security gate. Anthropic also provides deeper repository scanning with its multi-agent scanner and pull request reviews through Code Review for Team and Enterprise plans. Each stage helps catch issues missed by the previous one.
What it does well is cheap: it puts your team’s actual rules in front of the model at the moment code is written, in a file any engineer can edit in five minutes, versioned in the repository like everything else.
Workaround for OpenRouter
Skip this if you are not on OpenRouter.
I was running Claude Code through OpenRouter instead of a first-party
Anthropic account. Sessions worked fine but the plugin did not, because both model-backed reviews default to Claude Opus 4.7 and my OpenRouter key had roughly the spending power of a library card. It asked for Opus. It got a polite note about credits.
The fix is environment variables that redirect the reviews to a model the key actually serves. Here is the relevant part of my .bashrc:
export OPENROUTER_API_KEY="your-key"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
export ANTHROPIC_AUTH_TOKEN="$OPENROUTER_API_KEY"
export ANTHROPIC_API_KEY=""
export ANTHROPIC_DEFAULT_SONNET_MODEL="openrouter/free"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="openrouter/free"
export ANTHROPIC_DEFAULT_OPUS_MODEL="openrouter/free"
export CLAUDE_CODE_SUBAGENT_MODEL="openrouter/free"
export SECURITY_REVIEW_MODEL="openrouter/free"
export SG_AGENTIC_MODEL="openrouter/free"
SECURITY_REVIEW_MODEL covers the end-of-turn review and SG_AGENTIC_MODEL covers the commit review. The plugin reads them independently of the session model, which is the point: you can run a cheap model for coding and a stronger one for review, or the reverse if you are watching spend.
Hooks run as subprocesses of Claude Code, so they inherit the environment of the shell that started claude. Putting these in .bashrc rather than typing them in a second terminal is the reliable way to make sure the reviews see them.
References
Anthropic. “Catch security issues as Claude writes code.” Claude Code documentation. https://code.claude.com/docs/en/security-guidance
Anthropic. “Hooks reference.” Claude Code documentation. https://code.claude.com/docs/en/hooks
Anthropic. “Automate actions with hooks.” Claude Code documentation. https://code.claude.com/docs/en/hooks-guide
Anthropic. “Settings.” Claude Code documentation. https://code.claude.com/docs/en/settings
Anthropic. “security-guidance plugin.” claude-plugins-official repository, GitHub. https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance
Anthropic. “Code Review.” Claude Code documentation. https://code.claude.com/docs/en/code-review
Anthropic. “Claude Security plugin.” Claude Code documentation. https://code.claude.com/docs/en/claude-security











Top comments (0)