Most code reaches production with an approval click, but an approval is not a security review, and the gap widens as AI tools multiply the volume of changes. Secure code review is the practice of examining source code, by people and tools together, to find vulnerabilities before release. This guide covers how to choose review methods, decide which changes get deep review, run a repeatable workflow, enforce the merge gate so it cannot be bypassed, and measure whether review is working. It is for AppSec engineers, engineering managers and security champions. How to write secure code in the first place is covered in the Secure Coding Guide; this guide is about checking it.
Key takeaways
- Review and analysis are different controls. NIST SSDF task PW.7.1 asks organisations to decide where a person reviews code and where tools analyse it; good programmes use both, deliberately.
- Depth should follow risk. The OWASP Code Review Guide recommends rating modules by exposure, value of loss and regulatory weight, and setting reviewer counts and required checks per risk level.
- The gate matters as much as the reviewer. Without branch rules that require independent approval and passing checks, review is optional in practice.
- Review the whole change, not only the diff. The XZ Utils backdoor sat in build macros, release tarballs and binary test files that source reviewers rarely read.
- AI reviewers assist, they do not approve. GitHub's own documentation says its AI code review can miss problems and should be supplemented by careful human review.
What secure code review covers
Secure code review sits in the verify stage of the development lifecycle. NIST SP 800-218 (SSDF v1.1) practice PW.7, "Review and/or Analyze Human-Readable Code to Identify Vulnerabilities and Verify Compliance with Security Requirements", has two tasks: PW.7.1, decide whether code review (a person looks at the code) and/or code analysis (tools find issues, alone or with a person) should be used; and PW.7.2, perform it against the organisation's secure coding standards and record and triage all issues in the team's workflow or issue tracker. Testing running code is a separate practice, PW.8.
- In scope: application source, scripts, infrastructure as code, CI/CD workflow files, database policies, build scripts, and instruction or rules files that steer AI coding tools.
- Out of scope here: coding standards and language-specific defences (see the Secure Coding Guide), runtime testing (see the Penetration Testing Guide) and AI-specific review checklists (see the AI-Generated Code Review Guide).
- Reference text: the OWASP Code Review Guide v2 (July 2017) remains the main open methodology. Its vulnerability chapters are based on the OWASP Top 10 2013, so pair its method with current lists: OWASP Top 10:2025, the 2025 CWE Top 25 and OWASP ASVS 5.0.0 (stable release, 30 May 2025).
Review methods compared
No single method finds everything. The table sets out what each method is good at and what it misses.
| Method | Finds well | Misses | Best use |
|---|---|---|---|
| Peer review on pull requests | Logic errors, design problems, missing tests, readability | Security flaws the reviewer does not recognise | Every change, as the baseline gate |
| Security-focused manual review | Authorisation logic, business logic abuse, trust boundary errors, crypto misuse | Volume: slow and expensive | High-risk modules and security-sensitive changes |
| SAST (static analysis) | Injection, unsafe APIs, tainted data flows, known bad patterns | Missing authorisation, business logic, context; produces false positives | Every pull request, blocking on high severity |
| Secret scanning | Hard-coded keys, tokens and passwords | Custom or low-entropy secrets without a pattern | Push protection on every repository |
| Software composition analysis | Known-vulnerable or unexpected dependencies | Malicious packages without a published advisory | Every change to manifests or lock files |
| AI code reviewer | Fast first pass, explanations, common flaw patterns | Can miss issues and hallucinate findings | Triage assistant before human review |
| Formal inspection or audit | Deep design and implementation flaws | Changes made after the audit | Before major releases, crypto, authentication components |
Hybrid review combines these: tools run first and block obvious problems, an AI assistant may summarise the change and flag candidates, and a human reviewer decides. The OpenSSF guidance on AI code assistants names CodeQL, Bandit, Semgrep and OWASP Dependency-Check as examples of analysis tools to keep in the pipeline. For evaluating products, see the Application Security Testing Buyer's Guide.
Risk-based triage: deciding what gets deep review
Deep security review cannot cover every change. The OWASP Code Review Guide says the intensity of review should follow the risk level of the module being changed, that management should own a reproducible way of assigning that risk, and that it would be irresponsible to rate everything high risk. It proposes three criteria: ease of exposure (is the code internet-facing?), value of loss (does it hold password hashing or a cosmetic change?) and regulatory controls. It also gives examples: changes to a level one module reviewed by three people including a security architect, and a quick single peer review for a level four module.
| Tier | Typical triggers | Reviewers | Required checks |
|---|---|---|---|
| 1 (critical) | Authentication, authorisation, session handling, cryptography, payments, tenant isolation, database access policies, CI/CD and build scripts | Peer plus security reviewer or champion; code owner approval | SAST, SCA, secret scan, tests including negative tests |
| 2 (high) | Internet-facing endpoints, file upload, deserialisation, outbound requests, new dependencies | Peer with security checklist; code owner approval | SAST, SCA, secret scan |
| 3 (standard) | Internal features with no new inputs or permissions | One peer | SAST, secret scan |
| 4 (low) | Documentation, copy changes, test-only changes | One peer | Secret scan |
Map tiers to paths in a CODEOWNERS file so that the right reviewers are requested automatically. On GitHub, the file can live in .github/, the repository root or docs/; the last matching pattern takes precedence; files over 3 MB are not loaded; and the CODEOWNERS file itself should have an owner so it cannot be quietly edited. Small organisations can collapse tiers 3 and 4; large ones should add a tier for regulated code. The Threat Modelling Guide helps identify which modules belong in tier 1.
A repeatable review workflow
A review harness is the fixed set of context, checks and steps every security review follows. Use this sequence for tier 1 and 2 changes:
- Get context: read the ticket, the threat model and what the change is meant to do. The OWASP guide stresses knowing what the business needs to protect, such as card data in a payment application.
- Check the attack surface: does the change add inputs, endpoints, ports, roles or permissions? If it does, can it be done without increasing exposure?
- Read the automated results: SAST, SCA and secret findings, and test coverage. Do not repeat what tools already confirmed; focus on what they cannot see.
- Trace data from source to sink: follow untrusted input to queries, commands, file paths, templates and outbound requests, checking validation and encoding on the way.
- Crawl for risky APIs: search the change for calls that touch the outside world, file I/O, user management, dynamic code execution and deserialisation.
- Apply the checklist: work through the categories below that the change touches.
- Look beyond the diff: read surrounding code, build scripts, generated files and binaries included in the change.
- Record and triage: log each finding with severity, CWE and fix owner in the issue tracker, as SSDF PW.7.2 requires, and confirm the fix in a follow-up review.
What to look for: a checklist mapped to ASVS 5.0 and CWE
| Area | Reviewer question | ASVS 5.0 | CWE (2025 Top 25 rank) |
|---|---|---|---|
| Injection | Are queries parameterised and OS calls protected? | V1.2.4, V1.2.5 | CWE-89 (2), CWE-78 (9) |
| Output encoding | Is output encoded for its context? | V1.2.1 | CWE-79 (1) |
| Dynamic code | Is eval() or expression evaluation avoided? | V1.3.2 | CWE-94 (10) |
| Authorisation | Is every function and data item checked at a trusted service layer? | V8.2.1, V8.2.2, V8.3.1 | CWE-862 (4), CWE-863 (17), CWE-639 (24) |
| Authentication | Does every critical function require authentication? | V6 Authentication | CWE-306 (21) |
| Files and paths | Are paths canonicalised and uploads restricted by type? | V5 File Handling | CWE-22 (6), CWE-434 (12) |
| Deserialisation | Is untrusted data ever deserialised into objects? | V1.5.2 | CWE-502 (15) |
| Outbound requests | Can users influence URLs the server fetches? Are redirects followed? | V15.3.2 | CWE-918 (22) |
| Mass assignment | Are bindable fields limited per action? | V15.3.3 | None in Top 25 |
| Secrets | Are secrets from a vault, least privilege, with rotation? | V13.3.1, V13.3.2, V13.3.4 | CWE-798 (not in Top 25) |
| Dependencies | Do new components come from the expected repository and appear in the SBOM? | V15.1.2, V15.2.4 | None in Top 25 |
| Configuration | Are debug modes off and source control metadata excluded? | V13.4.1, V13.4.2 | CWE-200 (20) |
See the OWASP ASVS Guide for choosing a verification level and the CWE Top 25 Guide for the weakness classes.
AI code review and reviewing AI-generated code
Two separate questions arise: using AI to review, and reviewing what AI wrote.
- AI as a reviewer: GitHub's responsible use notes for Copilot code review say it may miss problems or report ones that do not exist, and should be supplemented with careful human review. Treat AI comments as triage input. Do not count an AI approval towards required approvals.
- AI as the author: Perry et al. found that participants using an AI assistant wrote significantly less secure code and were more likely to believe it was secure. Veracode's 2025 study, a vendor figure, reported OWASP Top 10 weaknesses in 45% of test cases across more than 100 models. Reviewers should expect more volume, plausible-looking code and invented packages.
- Semantic review: pattern-based tools catch syntax-level flaws; reviewers must check meaning, such as whether an authorisation check tests the right tenant or whether error handling fails closed.
- Provenance: label AI-generated changes so reviewers know where to look harder. GitHub rulesets include "Require an additional approval for unattributed Copilot pull requests" (public preview).
The detailed checklist for AI output is in the AI-Generated Code Review Guide; agent and IDE settings are in the AI IDE and Coding Agent Security Guide.
Enforcing the gate and preventing bypass
A review only protects production if code cannot reach it any other way. On GitHub, these ruleset settings form the minimum gate for protected branches; other platforms have equivalents.
- Require a pull request before merging: with required approvals set to at least one.
- Require approval of the most recent reviewable push: approval must come from someone other than the last person to push, which stops an author approving their own late changes.
- Dismiss stale pull request approvals when new commits are pushed: forces re-review after the diff changes.
- Code owner review: required for tier 1 paths and for CODEOWNERS, workflow and rules files.
- Require status checks to pass before merging and Require code scanning results: block merges on failed tests or code scanning alerts at the chosen severity.
- Bypass permissions: keep the bypass list short, use named teams rather than broad roles, and alert on every use.
- Secret push protection: by default anyone with write access can bypass by giving a reason; each bypass is logged in the audit log. Delegated bypass restricts it to designated reviewers.
Bots and CI tokens are a frequent bypass route. In the Amazon Q Developer extension compromise, an inappropriately scoped GitHub token in a build configuration let an attacker commit code that was included in release 1.84.0 without review. Scope automation tokens so they cannot push to protected branches. See the CI/CD Security Guide.
Managing review burden, fatigue and latency
Review quality falls when reviewers face large changes and long queues. Practical levers:
- Size: keep changes small enough to read in one sitting. The OWASP guide suggests an inspection rate of around 250 lines per hour as a planning baseline, explicitly not a quality measure.
- Complexity: the OWASP guide uses McCabe cyclomatic complexity (decisions plus one) to prioritise, treating 1 to 10 as stable, 11 to 15 as medium risk and 16 to 20 as high risk.
- Noise: tune SAST rules until false positives are rare; an ignored tool is worse than none because it trains reviewers to dismiss findings.
- Expertise: Google's engineering practices tell reviewers who lack expertise in an area such as security to make sure a qualified reviewer is on the change, and to say which parts they reviewed.
- Capacity: a security champions programme spreads tier 2 review across teams so the AppSec team handles tier 1.
Rolling out a secure code review programme
- Baseline: export branch protection settings for every deploying repository and measure how many merges in the last 90 days had an independent approval.
- Tier the code: agree risk tiers with engineering leads and encode them in CODEOWNERS.
- Add tools in audit mode: run SAST, SCA and secret scanning without blocking for two to four weeks on a pilot group; tune rules.
- Turn on the gate: enable blocking for high-severity findings and required approvals, pilot repositories first, then by business unit.
- Train reviewers: teach the checklist and the workflow with examples from your own codebase.
- Roll back safely: if a rule blocks delivery, switch that check to evaluate mode for the affected repository with a time-limited exception, rather than removing it everywhere.
Detection and measurement
Monitor audit logs for merges without approval, bypass use, changes to rulesets and CODEOWNERS, and pushes to protected branches by tokens. Useful KPIs:
- Gate coverage: percentage of merges to protected branches with independent approval and passing checks (target 100%).
- Bypass rate: bypasses per month, each with a reviewed reason.
- Review latency: median time from ready-for-review to first response, by tier.
- Escape rate: vulnerabilities found in testing, bug bounty or production that a review should have caught, by CWE.
- Re-inspection defect rate: the OWASP guide's measure of defects remaining or introduced after fixes.
- Finding age: time to fix review findings by severity.
Framework mapping
| Framework | Reference | How secure code review meets it |
|---|---|---|
| NIST SSDF (SP 800-218) | PW.7.1, PW.7.2 | Defined review and analysis; findings recorded and triaged |
| NIST SP 800-53 Rev. 5 | SA-11 Developer Testing and Evaluation; SA-11(1) Static Code Analysis; SA-15; CM-3 Configuration Change Control | Review and static analysis as developer testing; approval before change |
| NIST CSF 2.0 | PR.PS-06; ID.RA-01 | Secure development integrated and monitored; vulnerabilities identified and recorded |
| CIS Controls v8.1 | Control 16 Application Software Security | Security life cycle of in-house developed software |
| ISO/IEC 27001:2022 Annex A | A.8.25 Secure development life cycle; A.8.28 Secure coding; A.8.29 Security testing in development and acceptance | Review as part of secure development and acceptance |
| MITRE ATT&CK | T1195.001, T1195.002 | Review of dependency and build changes reduces supply chain compromise |
Common failure patterns
- Rubber-stamp approvals: approvals arrive within seconds of a large change. Track time-to-approve against change size.
- Reviewing only the git diff: the XZ Utils backdoor payload lived in release tarballs, a modified build macro and binary test files; compare release artefacts with tagged source and review build tooling.
- Trusted contributors exempt from scrutiny: in the same case, a contributor built trust over about two years before gaining release rights. Separate release rights from commit access and require more than one approver.
- Automation that skips the gate: over-scoped bot and CI tokens push directly to protected branches, as in the Amazon Q case.
- AI approval counted as review: an AI reviewer's pass is treated as sufficient, despite vendor warnings that it can miss problems.
- Findings that go nowhere: comments are resolved in the pull request but never logged, so recurring CWE classes are never fixed at the root.
Practitioner checklist
- Document where review, analysis or both are required, per SSDF PW.7.1.
- Assign a risk tier to every repository or module and encode it in CODEOWNERS, with an owner for the CODEOWNERS file itself.
- Require a pull request, independent approval of the latest push and stale approval dismissal on every protected branch.
- Block merges on high-severity SAST and code scanning results, failed tests and detected secrets.
- Restrict bypass permissions and secret push protection bypass to named teams, and alert on use.
- Scope bot and CI tokens so they cannot push to protected branches.
- Give tier 1 changes a security reviewer and use the ASVS-mapped checklist.
- Review build scripts, workflow files, binaries and AI instruction files, not only application code.
- Log every finding with CWE and severity, and report escape rate and gate coverage monthly.
Standards and references
- NIST: SP 800-218 Secure Software Development Framework (SSDF) Version 1.1
- OWASP: Code Review Guide
- OWASP: Application Security Verification Standard 5.0
- MITRE: 2025 CWE Top 25 Most Dangerous Software Weaknesses
- NIST: SP 800-53 Rev. 5
- GitHub Docs: Available rules for rulesets
- Google Engineering Practices: What to look for in a code review
- Perry et al.: Do Users Write More Insecure Code with AI Assistants?
Related NHI Mgmt Group resources: Secure Coding Guide · CWE Top 25 Guide · AI-Generated Code Review Guide · Application Security Guide · Software Supply Chain Security Guide