Blog
Secure code review: a practical guide and checklist
What a secure code review covers, how it fits with automated scanning, a checklist mapped to the OWASP Top 10, and what changes when AI wrote the code.
Alex Mercer
A secure code review is a read of source code aimed at finding security flaws, such as injection, broken access control, exposed secrets and risky dependencies, before the code ships. The practical version runs on every pull request that touches a trust boundary: scanners catch the known patterns first, and a reviewer checks what they can't, such as authorization logic, business rules and whether the change weakens a control that already exists.
OWASP's Secure Code Review Cheat Sheet defines it as "the process of manually examining source code to identify security vulnerabilities that automated tools often miss." A security code review uses the same pull request and the same diff as any other review. What changes is the question the reviewer asks of each line: how could someone abuse this?
If coding agents write much of your code, our guide to AI code security covers the flaws research keeps finding in AI-generated code.
What a secure code review covers
OWASP separates security-focused review from functional review by what it targets: input validation, authentication, authorization, cryptography and potential attack vectors.
OWASP describes two kinds of secure code review. Its hybrid approach combines them: baseline reviews for high-risk components, diff-based reviews for routine changes.
Diff-based review | Baseline review | |
|---|---|---|
Scope | The changes in a pull request or commit | The whole codebase |
When | Every pull request, feature completion, hotfixes | New applications, major releases, legacy systems coming under review, compliance cycles, after an incident |
First questions | What does this change do to existing security controls? What new attack vectors does it add? | Where are the entry points, trust boundaries and high-risk functions? |
The diff-based steps in OWASP's cheat sheet make a good default for pull requests: analyze the impact on existing security controls, identify new attack vectors, verify security at modified trust boundaries, check new integrations, and make sure nothing regressed.
NIST's Secure Software Development Framework (SP 800-218, version 1.1, still the latest final version) makes this a named practice, PW.7. It separates code review, where "a person looks directly at the code to find issues," from code analysis, where "tools are used to find issues in code." It also asks teams to record and triage every issue found in the development team's workflow or issue tracker.
How secure code review fits with automated scanning
Each kind of check reads something different, so none of them replaces the others.
Check | What it examines | Good at | What it leaves to the reviewer |
|---|---|---|---|
Static analysis (SAST) | Source code, without running it | Well-known flaws such as SQL injection, on every commit | Authentication, access control and crypto misuse; configuration that isn't in the code; sorting real findings from false positives |
Software composition analysis (SCA) | Third-party components and their versions | Known vulnerabilities, outdated components, license terms | Whether a new dependency is needed, and whether it is the package you meant |
Secret scanning | Code and config, for credential patterns | Keys and passwords committed by mistake | Revoking or rotating anything that already leaked |
Dynamic testing (DAST) | The running application, from the outside | Cross-site scripting, SQL injection, command injection, path traversal, insecure server configuration | Code paths the scan never reaches, and logic that needs context |
AI code review | The pull request, with context from the rest of the repository | A first pass on every pull request for logic bugs and security issues | Final judgment on risk, design and intent |
Secure code review | The change, its callers and the controls around it | Business logic, authorization, cryptographic misuse, race conditions | It can't cover every line, so point it at risky changes |
The table draws on OWASP's pages on source code analysis tools, DAST and component analysis. The OWASP page on static analysis is frank about its limits: it says such tools "can automatically identify only a relatively small percentage of application security flaws" and produce "high numbers of false positives."
OWASP's cheat sheet describes how the pieces fit. Run the automated tools before the manual review, use their findings to guide deeper investigation, apply human judgment to filter false positives, and focus manual effort where tools can't reach. For injection specifically, A05:2025 Injection says detection "is best achieved by a combination of source code review along with automated testing."
Secure code review checklist, grouped by risk
We mapped each group to a category in the OWASP Top 10:2025. Many items come from OWASP's cheat sheet or a Top 10 entry; others, such as passing command arguments as a list, verifying JWTs and testing denied paths, are common practice. Drop what doesn't apply to your stack and add your team's own rules. For the non-security half of a review (correctness, readability, tests), use our complete code review checklist.
Input handling and injection
Maps to A05:2025 Injection, and to A08:2025 for deserialization.
Inputs are validated on the server, using allowlists rather than blocklists.
Queries use parameters. No SQL or NoSQL is built by concatenating input, and ORM filters don't take raw user objects.
No shell command is built from input. Arguments go to the process as a list.
Output is encoded for its context: HTML, JavaScript, CSS or URL.
File paths from input are normalized and kept inside an allowed directory.
Untrusted data is not deserialized into objects, and XML parsers have external entities turned off.
Request bodies bind only to an allowlist of fields, to prevent mass assignment.
Server-side requests to user-supplied URLs are checked against an allowlist.
For language-specific patterns, see Node.js security patterns every code reviewer should enforce.
Authentication and sessions
Maps to A07:2025 Authentication Failures.
Passwords are hashed with a slow, salted algorithm.
Login, password reset and MFA endpoints block repeated failures quickly, so brute force and credential stuffing can't run unchecked.
Session tokens have at least 128 bits of entropy and are invalidated on logout and timeout.
Session cookies are set HttpOnly, Secure and SameSite.
Sensitive actions, such as changing an email address or password, require re-authentication.
Password reset links are time-limited.
JWT signatures and expiry are verified before any claim is trusted.
For a deeper pass on login and session code, see our security review checklist for PRs touching authentication.
Access control
Maps to A01:2025 Broken Access Control.
Every new endpoint enforces authorization on the server, and access is denied by default.
Object-level checks confirm the record belongs to the caller. Missing ones cause insecure direct object references (IDOR).
Admin functions are protected, and users can't change their own roles.
Horizontal and vertical privilege escalation are both covered: another user's data, and another role's actions.
CORS allows only trusted origins.
New cloud permissions and service accounts grant only what the code uses.
Authorization logic lives in one place rather than being repeated in each handler.
Tests cover the denied paths: no session, another user's record, a role without access.
A missing object-level check looks like this, on a route that checks who the caller is but not what they may touch:
A review comment might say: "requireAuth confirms the caller is signed in, not that this invoice is theirs. Scope the query by account_id and return 404 when nothing matches."
Secrets and cryptography
Maps to A04:2025 Cryptographic Failures.
No keys, tokens or passwords in code, tests, fixtures or config. Secrets come from a secret store and can be rotated.
No MD5 or SHA-1 for anything security-related, and no homegrown cryptography.
Tokens, reset codes and IDs that must be unguessable come from a cryptographically secure random generator.
IVs and nonces follow the rules of the cipher mode: unpredictable for CBC, unique per key for GCM.
TLS certificate and hostname validation stay on.
Every key has an owner, a storage location and a rotation plan.
If a real secret was committed, revoke or rotate it before anything else. Removing it from the code does not remove it from git history.
Dependencies
Maps to A03:2025 Software Supply Chain Failures and A08:2025 Software or Data Integrity Failures.
Each new dependency is needed, exists on the registry under that exact name, is maintained, and comes from an official source.
Versions are pinned in a lockfile, and lockfile changes are read, including transitive dependencies.
New and updated versions are checked against CVE, NVD or OSV data.
Changes to CI/CD workflows get the same review as application code.
A03:2025 also states the principle behind requiring review at all: "No single person should be able to write code and promote it all the way to production without oversight from another human being."
Logging and errors
Maps to A09:2025 Security Logging and Alerting Failures and A10:2025 Mishandling of Exceptional Conditions.
Logins, failed logins and high-value transactions are logged.
No passwords, tokens or personal data end up in logs, and log data is encoded so it can't inject into logging or monitoring systems.
Error responses don't expose stack traces or internal details.
Errors fail closed. A failed check denies access, and a failed multi-step transaction rolls back completely.
How to run a secure code review on a pull request
Read the description and the file list first. Mark what crosses a trust boundary: new endpoints, new inputs, new outbound calls, changed permissions.
Read the scanner output before the code. Triage it, and note which areas the tools can't judge.
Trace data from source to sink. Follow each new input through validation and business logic to where it lands: a query, a file, a response, a log line.
Check the controls the change touches as well as the new lines. A small edit to a middleware or a shared helper can weaken every route that uses it.
Think like an attacker. Ask how the feature could be misused: skipped steps, replayed requests, another user's IDs, concurrent requests.
Write findings someone can act on. OWASP's finding template covers a title, severity, CWE, location, impact, reproduction steps and a recommended fix.
Record and triage everything. Following NIST's PW.7, findings go into the team's tracker, including the low-severity ones.
Using the OWASP Code Review Guide and OWASP Top 10
The OWASP Code Review Guide is OWASP's book for people who review code. Its first section covers why and how to review. The second covers types of vulnerabilities and how to spot them, with examples of what not to do and what to do. The appendix includes a reviewer checklist. The current PDF dates from July 2017, and its vulnerability chapters mostly follow the OWASP Top 10 from 2013.
Use the guide for method. For current risk categories, use the OWASP Top 10:2025. For a current checklist, use the Secure Code Review Cheat Sheet.
OWASP Top 10:2025 | Where it shows up here |
|---|---|
A01 Broken Access Control | Access control |
A02 Security Misconfiguration | Access control (cloud permissions), logging and errors (stack traces in error responses) |
A03 Software Supply Chain Failures | Dependencies |
A04 Cryptographic Failures | Secrets and cryptography |
A05 Injection | Input handling and injection |
A06 Insecure Design | Mostly a design-stage concern; step 5 of the process (thinking like an attacker) catches some of it |
A07 Authentication Failures | Authentication and sessions |
A08 Software or Data Integrity Failures | Dependencies, and deserialization under input handling |
A09 Security Logging and Alerting Failures | Logging and errors |
A10 Mishandling of Exceptional Conditions | Logging and errors |
Our OWASP Top 10 guide covers each category in more depth.
What changes when AI wrote the code
The checklist stays the same. The emphasis shifts, because research keeps finding the same weaknesses in AI-generated code:
Injection gets a closer look. In Perry et al.'s user study (ACM CCS 2023), 36% of participants with an AI assistant wrote SQL-injectable code, against 7% without one. The assistant often concatenated strings instead of using prepared statements.
Every new dependency gets checked. Spracklen et al. (USENIX Security 2025) found that 19.7% of the package references generated by 16 models named packages that don't exist. Many of those names repeat across runs, so attackers can register them in advance.
Secrets get searched for. Code completion tools can reproduce credentials from their training data (Huang et al., FSE 2024).
Old defaults get questioned. In Pearce et al.'s study (IEEE S&P 2022), Copilot often hashed passwords with MD5 or a single round of SHA-256.
The author's confidence counts for less. Perry et al. also found that participants with an AI assistant were more likely to believe they had written secure code. Ask which parts an agent wrote and whether the author has read them, and don't let an agent approve or merge its own change.
Rates also differ by model. On cubic's Bug Bench, the seven models ranked for security and privacy bugs run from 0.56 for GPT-5.6 Sol, 44% below average, to 1.50 for Claude Opus 5.5, 50% above the all-model rate. The rates are observational: they reflect the code each model was used for as well as the model.
Volume is the other change. When agents open more pull requests than people can read closely, an AI reviewer can take the first pass on each one. As a GitHub app, cubic reviews every pull request in minutes and leaves inline comments with suggested fixes, so human reviewers can spend their time on design and intent. Our guide to AI code review covers how to roll one out and measure it.
Parts of the checklist can also run as written review rules. Flag Security Vulnerabilities covers the injection, secrets and weak-crypto items, Require API Auth, Validation, and Tenant Scoping covers missing auth checks and client-supplied tenant or account IDs, and Prevent Sensitive Data in Logs covers the logging item. Paste one into AGENTS.md and your coding agent follows it while it writes code.
Common mistakes in secure code reviews
Treating a clean scan as a clean review. OWASP lists authentication problems, access control issues and insecure use of cryptography as hard for static analysis to find automatically.
Reading only the changed lines. The first diff-based step in OWASP's cheat sheet is to analyze the impact on existing security controls, and that means reading callers and shared code too.
Checking dependencies at release time. Review a dependency in the pull request that adds it, while removing it is still cheap.
Leaving findings in chat. NIST's PW.7 asks teams to record and triage discovered issues in their workflow or issue tracker, so findings survive the conversation and show up in audits.
Dropping low-severity findings without triage. Triage everything, then decide. A low-severity bug can still matter in combination with another one.
FAQ
What is a secure code review?
It is a review of source code that looks specifically for security flaws, such as injection, broken access control, exposed secrets and vulnerable dependencies, before the code ships. OWASP describes it as manually examining source code to find vulnerabilities that automated tools often miss. It works best on every pull request, with periodic full-codebase reviews for high-risk components.
Are secure code reviews worth it?
For code that handles authentication, authorization, payments, personal data or untrusted input, yes. OWASP notes that static analysis tools find only a relatively small percentage of application security flaws, and that access control and authentication problems are hard to detect automatically. Keep the cost down by reviewing small pull requests as they land rather than auditing a whole release at the end.
Is AI-generated code safe to merge without review?
No. Peer-reviewed studies have found vulnerabilities in a large share of AI-generated code, including about 40% of the programs GitHub Copilot wrote for high-risk scenarios in one study. Review it with the same checklist, with extra attention to injection, new dependencies and hard-coded secrets.
Which SAST tool is best?
None is best for every team. Options include GitHub's CodeQL, Semgrep Code, Snyk Code and SonarQube Server, and OWASP lists many more, without endorsing any, on its page of source code analysis tools. Pick one that supports your languages and frameworks, runs on every pull request and produces findings your team fixes, then compare real findings against false positives on code you know. Whichever you pick, it won't judge authorization or business logic for you, so it supports a secure code review rather than replacing one.
