Software Securityhome
Fix a findingSearch
Phase 3 · Development

Security code review

Security code review is a person other than the author reading a change for what it lets someone do: which inputs it accepts, which permission checks run, what it sends back and how it fails. It complements scanners, which find known patterns but not a missing business rule.

Scanners find known patterns; a reviewer who knows the rules finds the missing check. A new download route can check the session and still stream any report by id, because nothing checks that the report belongs to the caller. OWASP says manual review is best at business logic, complex security code and context-specific flaws. A required review also stops one compromised or careless account from merging alone.

Who
A reviewer other than the author on every change, plus a security reviewer or champion named in CODEOWNERS for sensitive paths
When
On each pull request, after the automated checks have run and before merge
How often
Every pull request, with a deeper review for authentication, authorization, crypto, parsers, payments and build files
You end up with
An approval of the final revision, findings fixed or filed with an owner, and a regression test for each confirmed flaw

Do this

  1. Require a non-author approval of the final revision

    Protect the default branch so changes merge only through a pull request approved by someone other than the last pusher, and dismiss stale approvals when new commits arrive. On GitHub these are ruleset or branch protection settings; on GitLab, approval rules with Prevent approval by merge request creator (Premium and Ultimate). Leave no standing bypass for administrators.

  2. Route sensitive paths to a security reviewer

    Name owners in a CODEOWNERS file for authentication, authorization policy, crypto, parsers, payments, secrets handling, CI workflows and lockfiles, and require code owner review. Own the CODEOWNERS file too, so a change cannot remove its own reviewer. GitHub requests the owners automatically, and an approval from any one listed owner is enough.

  3. Start from what the change lets someone do

    Name the new capability before reading lines: a route, a job, an export, a field. Then follow one request through the real code, including middleware and helpers outside the diff: where the input comes from, which identity and permission checks run, and when the first byte, write or queued job happens. A helper called requireUser proves a name, not a permission.

  4. Check each boundary the change touches

    Use a short checklist per boundary rather than one long list: values reach queries and commands through the safe API (Secure coding), output is encoded for its context, the full object and field permission runs before any effect, failures deny and log no secrets, no credential is in the diff, and each new package is real and pinned (Dependency selection). The table below maps each to OWASP ASVS 5.0.

  5. Use the automated findings to aim the review

    Read the static analysis, secret scanning and dependency results on the pull request first (CI security checks), then spend human attention where tools are weak: authorization, business rules and multi-step flows. OWASP's Secure Code Review Cheat Sheet recommends using automated findings to prioritize manual review, and combining diff-based reviews with deeper reviews of high-risk components.

  6. Review AI-generated code the same way

    Hold generated code to the same evidence as any other change: check that the APIs it calls exist and behave as claimed, and that every package it adds exists and is the one intended. A USENIX Security 2025 study found that code models suggest packages that do not exist, which an attacker can register. AI coding assistants covers the rest.

  7. Write findings someone can reproduce, then close them

    State the trigger, the broken rule, the consequence, the location and the fix, for example: Alice can request Bob's report id and the handler streams it without calling canDownload. Fix it in the pull request or record it in the tracker with an owner, as NIST SSDF task PW.7.2 asks, and close it with a test that fails on the old code, with an allowed case that still passes.

Done when

Branch rules require an approving review from someone other than the author before merge.

Mark it in the gap check

Common mistakes

  • Reviewing only the diff. The missing check is often outside it, in middleware, a shared helper or an error path that the change now reaches.
  • Leaving administrators able to bypass review. On GitHub, branch protection rules do not apply to admins unless you turn on Do not allow bypassing the above settings, and every entry in a ruleset's bypass list can merge around review.
  • Counting an approval of an earlier revision. Without dismissing stale approvals or requiring approval of the most recent push, the author can add a commit after approval and merge it unreviewed.
  • Accepting a confident explanation, a clean scan or a test's name as evidence. A test called denies_foreign_report can pass with a fixture that never exercises the real policy.
  • Pasting proprietary code or secrets into an unapproved external review service, AI or otherwise, which sends them outside your control.

What to ask, by what the change touches

One question per boundary keeps the review short. The OWASP ASVS 5.0 chapter holds the detailed requirements to check against.

What to ask, by what the change touches: table
The change touchesAskASVS 5.0 chapter
A new route, job or exportIs the full object, function and field permission checked before any effect?V8 Authorization
Queries, commands, templates or parsersDoes each value reach its interpreter through a data interface?V1 Encoding and Sanitization
Uploads or archivesAre type, size, path and serving rules enforced?V5 File Handling
Login, sessions or tokensAre expiry, revocation and binding unchanged or stronger?V7 Session Management, V9 Self-contained Tokens
CryptographyDoes it use a vetted library, current algorithms and a cryptographically secure random generator?V11 Cryptography
Errors and logsDo failures deny, and do logs leave out secrets?V16 Security Logging and Error Handling
Secrets and configurationAre credentials read from a secrets manager, and is debug output off?V13 Configuration
DependenciesIs each new package real, maintained and pinned in the lockfile?V15 Secure Coding and Architecture

Tools and guides

Standards

NIST SSDF 1.1
PW.7 Analyze Human-Readable Code to Identify Vulnerabilities and Verify Compliance with Security RequirementsPS.1 Protect All Forms of Code from Unauthorized Access and Tampering

Sources

  1. OWASP Secure Code Review Cheat Sheet
  2. NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1 (PW.7.2 and PS.1.1). February 2022.
  3. GitHub Docs: Available rules for rulesets
  4. GitHub Docs: About protected branches
  5. GitHub Docs: About code owners
  6. GitLab Docs: Merge request approval settings
  7. OWASP ASVS 5.0.0: chapters. Version 5.0.0.
  8. Spracklen et al.: We have a package for you! Package hallucinations by code-generating LLMs (USENIX Security 2025)
  9. OWASP SAMM: Security Testing

Find your next answer

Type to search. Search runs in your browser.

Searches run in your browser, but the host can infer them from the index files they load. The address shows your search so you can bookmark or share it.