Roughly half of the pull requests you review now contain code an assistant wrote, and the humans who accepted it often understand it less deeply than code they typed themselves.
Assistant-written code is exactly the review surface where a fast, well-prompted AI pass earns its keep — as long as you treat every finding it produces as a lead to confirm, never a verdict to ship. This playbook turns an LLM into a second reviewer over your own repository: it reads the diff, flags likely vulnerabilities with reasoning, and hands you a ranked list you verify against a static analyzer and the running code.
AI review widens coverage and surfaces classes of bug a tired human skims past; it does not replace the human sign-off or the static analyzer that grounds it.
Skip it for a one-line config tweak, and never point it at a third party's code — this is for securing code you own and are authorized to review.
Gather the exact diff and its context. Export the change so the model reviews what actually merges, not an approximation:
git diff --unified=5 origin/main...HEAD > /tmp/review.diff
Prompt for findings with reasoning and a severity, not a verdict. Ask for evidence you can check:
You are a secure-code reviewer. Review the diff below for security
vulnerabilities in code I own and am authorized to review.
For each finding, give:
- file and line
- vulnerability class (map to CWE where you can)
- a one-sentence explanation of the exploitable path
- severity (Critical/High/Medium/Low) and your confidence (High/Med/Low)
- the minimal safe fix
Report every issue you find, including low-confidence ones — I will
verify and filter. Do not withhold findings for being uncertain. Flag
anything that looks assistant-generated and plausible-but-wrong
(invented APIs, missing validation, copy-pasted unsafe patterns).
DIFF:
<paste /tmp/review.diff>
Expected output: a table of findings. A good pass catches things like a string-formatted SQL query, a verify=False on a TLS call, an authorization check that reads the wrong user ID, or a secret hardcoded in a "temporary" test helper.
Cross-check every finding against a static analyzer. Run Semgrep or CodeQL over the same code and compare. Where the tool and the model agree, your confidence is high; where only the model flags it, you have a lead to confirm manually; where only the tool flags it, ask the model to explain the tool's finding.
semgrep --config auto --json services/payments > /tmp/semgrep.json
Ask the model to reconcile the two lists. Paste the analyzer output back and have it explain agreements and disagreements, so you review a single merged list instead of two.
Confirm the real ones and write them up. For each surviving finding, produce a reviewer comment with the exploit path and the fix — see the companion remediation playbook for wording developers act on.
--config auto for a broad first pass and pair its findings with the model's.In a services engagement you frequently cannot paste a client's source into a public tool. Before prompting, strip identifying material — real hostnames, connection strings, customer identifiers, secrets, proprietary business logic — and review only the security-relevant slice, or reproduce the pattern abstractly ("a Flask route that builds a SQL query from a request arg"). Where the client's policy forbids external tools entirely, run a local model via Ollama for the review prose and keep Semgrep/CodeQL — which run fully offline — as the grounding layer. Confirm per-client tool approval before the first prompt, and log what left the boundary.