AI Code Review Prompts: Four Passes for Security, Correctness, Edge Cases and Test Gaps

Code displayed on a computer monitor during an AI-assisted code review

An AI code review prompt works when it gives the model one narrow job (security, correctness, edge cases or test gaps), the context a human reviewer would have (what the change is for, the language and framework, the surrounding code), and a strict output format that requires a line reference and a concrete failure scenario for every finding. A broad “review this code” request produces a long list of style remarks and generic advice that buries the one comment that matters. Narrow passes, each with its own prompt, catch more real bugs and are faster to triage.

This article lays out a four-pass review routine, gives a copy-ready prompt for each pass, shows how to make the output easy to verify, and covers the mistakes that make AI review noisy or misleading.

What an AI code review prompt is, and what it is not

An AI code review prompt is a structured instruction that asks a language model to inspect a change through a specific lens and report findings in a fixed shape. It is a first pass that runs before a human reviewer, not a replacement for one.

The division of labor matters. Google’s guide on what to look for in a code review lists design, functionality, complexity, tests, naming, comments, style, documentation and context. A model can help with several of these, especially spotting unhandled inputs, missing tests and well-known vulnerability patterns. It is much weaker at design and context questions: whether the change belongs in this service at all, whether it fits where the system is heading, whether it does what the product actually needs. Those stay with the human reviewer, who now has more time for them.

The four passes

Splitting review into passes works for the same reason that checklists work: a reviewer looking for one thing finds more of it. Each pass below has a role, a scope, and things it must ignore.

PassLooks forIgnoresWhen to run
1. SecurityInjection, broken access control, secrets, unsafe deserialization, data exposureStyle, naming, performanceEvery PR that touches input handling, auth, data or dependencies
2. CorrectnessLogic errors, wrong conditions, off-by-one, resource leaks, error handlingStyle, securityEvery PR with non-trivial logic
3. Edge casesInputs, states and timing that break the codeCode structureNew functions, parsers, anything handling external data
4. Test gapsBranches and failure paths with no testCode quality of the tests’ styleAny PR that adds or changes behavior

You do not need all four on every change. A documentation fix needs none; a new payment endpoint needs all four.

The shared preamble

Every pass starts with the same context block. It is the part people skip and the part that removes most false positives, because without it the model has to guess what the code is supposed to do.

Context for this review:
- Purpose of the change: <one or two sentences, or the PR description>
- Language / framework / versions: <e.g. Python 3.12, Django 5.1>
- How this code is reached: <public HTTP endpoint, internal job, CLI>
- Trust level of inputs: <which inputs come from users or other systems>
- Known constraints: <e.g. "must stay compatible with v2 API clients">

The diff is below, followed by the full current version of each changed
function so you can see surrounding code.

<diff>
PASTE DIFF
</diff>

<full_functions>
PASTE CHANGED FUNCTIONS IN FULL
</full_functions>

“How this code is reached” and “trust level of inputs” are what let the security pass tell a real injection from a string that only ever comes from your own config file. A good pull request description already contains most of this; the prompts for commit messages and pull request descriptions produce one in the right shape.

Pass 1: Security

The security pass uses the current OWASP Top 10 as its checklist, so findings come with a category you can look up. The latest edition is the OWASP Top 10:2025, whose categories run from A01 Broken Access Control to A10 Mishandling of Exceptional Conditions; the list below names the ones a diff-level review can realistically check.

Act as an application security engineer reviewing this change.
Review ONLY for security issues. Do not comment on style, naming,
performance or general code quality.

Check each of these explicitly and say "none found" for any with no
issue:
- Broken access control (A01:2025): missing or bypassable
  authorization checks, IDOR, trusting client-supplied IDs or roles
- Security misconfiguration (A02:2025): debug flags, permissive CORS,
  default credentials, verbose errors returned to clients
- Software supply chain (A03:2025): new or changed dependencies,
  unpinned versions, install scripts
- Cryptographic failures (A04:2025): weak algorithms, hardcoded keys,
  secrets in code or logs
- Injection (A05:2025): SQL, shell, template, path traversal, unsafe
  deserialization
- Authentication failures (A07:2025): session handling, token
  validation, password handling
- Mishandling of exceptional conditions (A10:2025): errors that fail
  open, swallowed exceptions in security-relevant paths

For each finding, output:
- Severity: high / medium / low
- OWASP category
- Location: file and line, with the exact line quoted
- Exploit scenario: one or two sentences, concrete (who sends what)
- Minimal fix
- Confidence: high / medium / low, and what context would confirm it

Why this shape:

  • “None found” per category forces the model to actually consider each one instead of stopping after the first finding.
  • The quoted line lets you verify the finding in seconds, and exposes findings about code that is not in the diff.
  • The exploit scenario is the best filter for false positives. If the model cannot describe who sends what to trigger the issue, the finding is probably theoretical.
  • Confidence plus missing context turns “maybe” findings into specific questions instead of noise.

If the change includes CI configuration, a dedicated checklist works better than a general prompt; see the checklist for reviewing an AI-generated GitHub Actions workflow. Regular expressions also deserve their own pass because of catastrophic backtracking, covered in the pre-merge checklist for AI-generated regex.

Pass 2: Correctness

The correctness pass asks whether the code does what the context block says it should.

Review this change for correctness only, against the stated purpose.
Ignore style and security.

Look for:
- Conditions that are inverted, incomplete or use the wrong operator
- Off-by-one errors in loops, slices, ranges, pagination
- Null / None / undefined values reaching code that assumes a value
- Error handling that swallows exceptions or returns misleading results
- Resources (files, connections, locks) not released on every path
- Behavior changes for existing callers that the purpose does not
  mention

For each finding: location with the quoted line, an input or sequence
of calls that produces the wrong result, what happens, what should
happen. If the code is correct for every case you considered, say so
and list the cases you checked.

Asking for the cases checked when nothing is found gives you something to evaluate. A list of three trivial cases is a sign the model did not look hard, and a prompt to look again with specific inputs usually turns something up.

Pass 3: Edge cases

This pass takes the stance of a tester trying to break the code rather than a reviewer reading it.

Act as a QA engineer whose job is to break this code.
List inputs, states or timing conditions that could cause incorrect
behavior or an unhandled exception. Consider: empty and very large
inputs, unusual characters and encodings, duplicates, concurrent calls,
partial failures of external calls, time zones and clock changes,
retries.

For each, give a concrete example input and say whether the code
(a) handles it correctly, (b) fails loudly, or (c) silently does the
wrong thing. Sort with (c) first; silent failures matter most.

The three-way split is the useful part. Code that fails loudly on bad input is often acceptable; code that silently returns a wrong answer rarely is.

Pass 4: Test gaps

The last pass compares the change with its tests.

Here is the changed code and its test file.
Identify branches, exception paths and boundary values in the changed
code that no test exercises or that tests exercise without a
meaningful assertion.

Return a table with columns:
Condition | Covered? (yes / no / weakly) | Suggested test (one line)

Do not write the tests yet.

“Weakly” catches tests that call the code without checking the result. When you are ready to fill the gaps, the unit test prompts take this table as their input.

Making AI review output easy to triage

The value of AI review depends on how fast you can separate real findings from noise. A few habits help:

  1. Verify the quoted line first. If it does not exist in the diff or the file, discard the finding.
  2. Try the scenario. For anything marked high severity, spend two minutes reproducing it or writing a failing test. Many findings resolve one way or the other in that time.
  3. Record outcomes. Mark each finding as fixed, not an issue, or deferred. After a few weeks you will see which passes are worth running on which parts of the codebase.
  4. Re-run after fixes. Fixes introduce new code, and the second pass is cheap.

Mistakes that make AI code review unreliable

  • No context. Without the purpose and trust boundaries, the model reports every string concatenation as injection and every missing check as a vulnerability.
  • Everything in one pass. Broad prompts produce broad, shallow results. One concern per prompt.
  • Changes that are too large. Google’s guidance on small changes suggests around 100 lines is usually a reasonable size and 1,000 is usually too large, and the same pressure applies to a model reviewing it. Review large changes function by function or file by file.
  • Treating the output as a verdict. “No issues found” from a model means no issues found in what it considered, nothing more. A human still approves the merge.
  • Reviewing untrusted code without caution. Code and comments are input to the model. A comment written to manipulate an AI reviewer is a real risk in pull requests from outside contributors; see prompt injection and how to defend against it.
  • Sending code you are not allowed to share. Check your organization’s policy on which models and providers may see source code before pasting proprietary diffs into a hosted chat.

Fitting this into a workflow

A practical starting point is to run the security pass on every pull request before a human looks at it, the way a linter runs, and run the other passes on changes with real logic. Teams that automate this usually trigger the security pass on each push to a PR branch and post findings as review comments, with a person deciding what to act on. Model choice matters less than prompt structure here: any current frontier model from Anthropic, OpenAI or Google will do better with a narrow prompt and good context than any of them will with “review this code”.

Sources

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top