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
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.
Route sensitive paths to a security reviewer
Name owners in a
CODEOWNERSfile for authentication, authorization policy, crypto, parsers, payments, secrets handling, CI workflows and lockfiles, and require code owner review. Own theCODEOWNERSfile too, so a change cannot remove its own reviewer. GitHub requests the owners automatically, and an approval from any one listed owner is enough.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
requireUserproves a name, not a permission.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.
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.
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.
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 checkCommon 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_reportcan 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.
| The change touches | Ask | ASVS 5.0 chapter |
|---|---|---|
| A new route, job or export | Is the full object, function and field permission checked before any effect? | V8 Authorization |
| Queries, commands, templates or parsers | Does each value reach its interpreter through a data interface? | V1 Encoding and Sanitization |
| Uploads or archives | Are type, size, path and serving rules enforced? | V5 File Handling |
| Login, sessions or tokens | Are expiry, revocation and binding unchanged or stronger? | V7 Session Management, V9 Self-contained Tokens |
| Cryptography | Does it use a vetted library, current algorithms and a cryptographically secure random generator? | V11 Cryptography |
| Errors and logs | Do failures deny, and do logs leave out secrets? | V16 Security Logging and Error Handling |
| Secrets and configuration | Are credentials read from a secrets manager, and is debug output off? | V13 Configuration |
| Dependencies | Is each new package real, maintained and pinned in the lockfile? | V15 Secure Coding and Architecture |
Tools and guides
- Workflow: secure a feature
- Tool: GitHub Actions workflow analyzer
- Fix cards: tested fixes by stack
- Review a code change through its trust boundaries
Turn a pull request into a small set of security claims that can be checked against the surrounding system and tests.
- Protect the source repository: rulesets, reviews and signed commits
Configure the controls every repository that ships software needs: protected branches and tags, required review with CODEOWNERS, signed commits, secret push protection and account security, mapped to the SLSA Source track, the OpenSSF OSPS Baseline and Scorecard.
- Enforce authorization for every object action
Authorize the authenticated subject, requested operation, and specific resource together; a valid login or unpredictable identifier is insufficient.
- Secure AI-assisted development with coding assistants and agents
Treat generated code, suggested packages, repository text and MCP servers as untrusted inputs, and confine coding agents with OS-level isolation and short-lived, narrowly scoped credentials.
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
- OWASP SAMM 2
- Security TestingDefect Management
Sources
- OWASP Secure Code Review Cheat Sheet
- NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1 (PW.7.2 and PS.1.1). February 2022.
- GitHub Docs: Available rules for rulesets
- GitHub Docs: About protected branches
- GitHub Docs: About code owners
- GitLab Docs: Merge request approval settings
- OWASP ASVS 5.0.0: chapters. Version 5.0.0.
- Spracklen et al.: We have a package for you! Package hallucinations by code-generating LLMs (USENIX Security 2025)
- OWASP SAMM: Security Testing