On this page#
What changes when an agent does this#
Claude Code security shifts the bottleneck from writing code to controlling authority, context, and verification. The agent can inspect a repository, propose coordinated changes, and run permitted tools quickly; it cannot decide which behavior is safe to change. Your real control surface is therefore the workflow around the agent, not the prompt alone.
That distinction matters in a repository with invariants: authorization boundaries, data ownership rules, compatibility promises, deployment assumptions, and behaviors that may not be encoded in tests.
The Claude Code overview explains the agent’s repository-aware workflow. Repository awareness is useful, but it is not proof that the agent has found every relevant dependency. A convincing patch can still violate an invariant that lives in operational knowledge, an external consumer, or an untested negative case.
Treat the agent as a fast, privileged contributor:
- Give it a bounded objective, not “secure this repository.”
- Separate investigation from modification.
- Restrict the files and commands it may touch.
- Require evidence for every claimed vulnerability.
- Review the final diff as hostile input.
- Run security-specific checks outside the agent’s narrative.
The wrong model is “the agent reviews, then I approve.” The better model is “the agent gathers evidence and drafts a patch; independent gates determine whether that patch survives.”
Photo by Christina Morillo on Pexels.
The prompt chain#
A secure prompt chain divides discovery, threat modeling, repair, and verification into separate stages. Each stage produces an artifact that the next stage must challenge. Do not ask Claude Code to find, fix, test, and summarize security problems in one turn: that bundles assumptions together and makes unsupported conclusions harder to detect.
The official Claude Code documentation should define how you configure permissions and interact with the tool. Your repository rules must define what the documentation cannot: protected paths, forbidden commands, required checks, and the invariants no agent may reinterpret.
Stage 1: establish scope without changing anything#
Start by forcing a read-only map of the attack surface. This prevents an early patch from anchoring the rest of the review around the first plausible issue.
Work in analysis-only mode. Do not edit files, install dependencies, or run
commands that change repository state.
Review only:
- <paths in scope>
Treat these as invariants:
- <security invariant>
- <compatibility invariant>
- <data or authorization invariant>
Identify trust boundaries, externally controlled inputs, sensitive operations,
and existing validation or authorization checks. For every claim, cite the
relevant file and symbol. Mark unknowns explicitly. Do not propose fixes yet.Why this works: it separates facts from remedies. If the agent cannot connect an input to a sensitive operation through concrete code, you have a hypothesis—not a finding.
Stage 2: turn observations into falsifiable findings#
Now require a testable abuse path. Use the OWASP Top Ten as a shared vocabulary for common application-security risk, not as a checklist that magically proves coverage.
Using the scoped repository map, produce candidate findings only where you can
describe:
1. attacker-controlled input,
2. the trust boundary crossed,
3. the sensitive operation reached,
4. the missing or insufficient control,
5. a minimal way to confirm or reject the claim.
Classify each finding with the closest OWASP Top Ten category when applicable.
Separate confirmed code evidence from assumptions. Do not edit files.Why this works: security language is cheap. A causal path is expensive. Requiring both the source and sink exposes findings built from pattern matching rather than repository behavior.
Stage 3: design the smallest repair#
Only confirmed findings advance. The repair plan must preserve named invariants and identify affected callers before any edit occurs.
For finding <ID>, propose the smallest repair that blocks the demonstrated abuse
path while preserving the listed invariants.
Before editing, list:
- files that must change,
- callers or consumers affected,
- tests that should fail before the repair,
- tests that should pass afterward,
- residual risks and unsupported assumptions.
Offer one preferred repair. Do not provide multiple vague alternatives.
Wait for approval before modifying anything.A vulnerability identifier from the NIST National Vulnerability Database can provide external context when one already applies, but resemblance is not identity. Never let an agent turn “similar to a known vulnerability” into “this repository is vulnerable” without a matching dependency, code path, and configuration.
Stage 4: implement under a file and command budget#
The implementation prompt should make scope expansion visible instead of allowing “necessary cleanup” to spread through the repository.
Implement only the approved repair.
You may modify:
- <exact files>
You may run:
- <exact test, lint, or analysis commands>
Do not update dependencies, generated files, lockfiles, configuration, or
unrelated formatting. Add the minimal regression test that demonstrates the
blocked abuse path. If another file or command becomes necessary, stop and
explain why before proceeding.
Finish with the changed files, invariant-by-invariant reasoning, test results,
and unresolved risks.For a reusable version of this staged workflow, the PairFoundry Review & Repair pack provides a more practical starting point than repeatedly improvising one giant security prompt.
The gate#
The gate is a deliberate human stop between the proposed patch and acceptance. The reviewer must inspect the abuse case, permission changes, security boundary, regression test, and complete diff before merge. A green test suite is supporting evidence; it is not authorization to merge a security-sensitive change.
Review these items in order:
- Finding validity: Can you trace attacker-controlled data to the sensitive operation?
- Boundary placement: Is the control enforced at the authoritative boundary, or merely in one caller?
- Failure behavior: Does rejection fail closed without leaking secrets or internal state?
- Regression test: Does the test exercise the abuse path rather than only the helper added by the patch?
- Diff containment: Are there unrelated edits, dependency changes, weakened checks, or new bypasses?
- Operational impact: Could the repair break trusted automation, existing clients, or recovery procedures?
The OWASP Top Ten helps reviewers name familiar failure classes, but the repository’s invariants remain the acceptance criteria. This is where teams often go wrong: they review whether the code looks cleaner, not whether the original exploit path is closed at every reachable entry point.
Claude Code security reviews should therefore end with a reviewer-owned decision record: confirmed issue, accepted patch scope, evidence examined, commands run, residual risk, and rollback trigger. The agent may draft it. The human owns it.
Photo by Christina Morillo on Pexels.
What it gets wrong#
Claude Code most often fails by producing a locally coherent answer that is globally incomplete. It can overstate a pattern match, miss an indirect caller, repair validation at the wrong layer, or write a test that confirms its implementation instead of the security property. Fluency makes these failures unusually easy to approve.
Watch for these concrete signals:
| Failure mode | Recognition signal | Required response | |---|---|---| | Phantom vulnerability | No complete input-to-operation path | Reject until the path is demonstrated | | Wrong-layer validation | Check exists only in one UI, route, or caller | Move enforcement to the authoritative boundary | | Partial caller coverage | Search results or call graph contain unreviewed entry points | Expand analysis before editing | | Self-fulfilling test | Test directly targets the new helper | Test through the real external boundary | | Permission widening | New wildcard, fallback, or default-allow behavior | Block the patch | | Scope laundering | Formatting, refactors, or dependencies appear in the diff | Split or discard unrelated changes | | False confidence | Summary says “secure” or “fully fixed” | Demand bounded claims and residual risks |
Consult Claude Code’s documentation for the tool’s supported controls, but do not confuse tool permission controls with application security. Preventing an agent from running an unapproved command does not prove that the code it wrote enforces tenant isolation correctly.
When the repository lacks stable tests, clear invariants, or an identifiable security boundary, do not use an autonomous repair loop. Use the agent for read-only mapping and question generation. The free PairFoundry foundations track is the better next step when the workflow itself is not ready; the broader pack overview shows where review fits alongside other repository work.
Rollback#
Rollback should restore a known repository state without preserving generated noise, partial dependency changes, or hidden configuration edits. Define the rollback unit before implementation: one isolated branch or change set, an explicit baseline, no unrelated work, and a short list of verification commands that must pass after reversal.
Use this sequence:
- Record the clean baseline and approved scope before edits.
- Keep the security repair separate from refactoring and dependency work.
- Stop immediately if the agent touches an unapproved file or changes an invariant.
- Inspect the entire diff, including generated and configuration files.
- Revert the isolated change set using your normal version-control workflow.
- Restore any external state separately; source rollback cannot undo migrated data, rotated credentials, or deployed configuration.
- Run the baseline verification commands again.
- Reopen the finding with the failed assumption documented.
The key rule is simple: never ask the same agent session to “clean up whatever went wrong” after uncontrolled scope expansion. Its context already contains the assumptions that produced the bad patch. Return to the baseline, narrow the finding, and begin a fresh chain.
More agent workflows belong in the PairFoundry workflows hub. The reusable principle is consistent: isolate the change, preserve a known-good state, and make recovery cheaper than rationalizing a questionable diff.
Photo by Lukas Blazek on Pexels.
Related reading#
- GitHub Copilot planning: the prompt chain we actually run
- Python MCP server, with the guardrails that keep it honest
FAQ#
Where should I avoid using this workflow?#
Do not allow agent-led repair where you cannot state the invariant, isolate the change, or independently verify the result. Production credentials, irreversible data operations, incident containment, and poorly understood authorization systems require tighter human control. Read-only analysis may still help, but autonomous modification is the wrong tool.
How is this different from following the official Claude Code guidance?#
The official overview explains the product and its operating model. This workflow adds repository-specific security governance: staged prompts, falsifiable findings, exact modification budgets, an independent human gate, and a predeclared rollback unit. Official controls are necessary; they are not your application’s threat model.
What breaks when a whole team uses Claude Code security reviews?#
Teams lose consistency when every engineer invents prompts, assigns different meanings to “confirmed,” or accepts agent-written summaries without inspecting diffs. Standardize invariants, evidence requirements, allowed commands, gate ownership, and decision records. Otherwise, review quality depends on who happened to prompt the agent.
What should I do when the agent changes files outside the approved scope?#
Stop the run and treat the patch as untrusted. Inspect the complete diff, revert the isolated change set, verify the baseline, and restart with narrower permissions. Do not preserve the “useful parts” unless each change is independently understood; that shortcut defeats the scope boundary.
When is an agent-generated security fix ready to merge?#
It is ready only when the abuse path is demonstrated, the control sits at the authoritative boundary, the regression test exercises that path, the complete diff stays within scope, required checks pass, and a human accepts the residual risk. “Claude says it is fixed” is never merge evidence.