Most vulnerabilities are introduced during development and survive code review. Not because reviewers are careless — but because most developers aren't trained to spot security issues during review. Security is treated as someone else's job, something that happens later in the pipeline.
That's too late. Every vulnerability caught in code review is cheaper, faster, and safer to fix than one caught in production — or by an attacker.
The Security Review Mindset
Code review for functionality asks: "Does this code do what it's supposed to?" Security review asks a different question: "What can this code be made to do?"
Functional Review Thinks
- •Does this input get processed correctly?
- •Does error handling work for expected errors?
- •Is the API response formatted correctly?
- •Does the UI render properly?
Security Review Thinks
- •What happens if this input is malicious?
- •What information do error messages leak?
- •Can the API be called in an unintended order?
- •Can the UI be manipulated to execute scripts?
The Critical Patterns to Watch For
1. Input Handling
Every piece of user input is a potential attack vector. During review, trace every input from entry to use:
SQL queries with string concatenation
Any SQL query built by concatenating user input is vulnerable to SQL injection — still the most dangerous web vulnerability as we covered in SQL Injection in 2026. Always use parameterized queries.
HTML output without encoding
User input rendered in HTML without proper encoding enables XSS. As we detailed in XSS in 2026, even modern frameworks have escape hatches where raw HTML rendering bypasses protection.
File paths from user input
User-controlled file paths enable path traversal. A filename like ../../etc/passwd can access files outside the intended directory. Always validate and sanitize file paths.
URLs from user input
User-provided URLs used in server-side requests enable SSRF. As we covered in SSRF attacks, the server can be tricked into accessing internal resources, cloud metadata, or other services.
⚠️Trust Boundaries
The most important question in secure code review: Where does trusted data end and untrusted data begin? Every crossing of this boundary needs validation. User input, API responses from external services, database values that were originally user-supplied, file contents — all untrusted.
2. Authentication and Session Management
Password Handling
Passwords hashed with bcrypt/argon2 (not MD5/SHA1). No plaintext passwords in logs or error messages. Password reset tokens are random, single-use, and expire.
Session Security
Session tokens are random and long enough (128+ bits of entropy). Sessions invalidated on logout. Session fixation prevented by rotating session ID on login.
Token Validation
JWTs verified with proper algorithm (not "none"). Token expiration enforced server-side. Refresh tokens stored securely and rotated on use.
Multi-Factor
MFA tokens validated server-side with rate limiting. Backup codes are single-use. MFA bypass for "trusted devices" has reasonable expiry.
As we covered in Authentication Bypass Techniques, authentication is one of the most commonly flawed components in web applications.
3. Authorization
The most overlooked category in code review. Authentication verifies who you are; authorization verifies what you can do:
Authorization Review Checklist
Object-level authorization
Every API endpoint that accesses a resource by ID must verify the requesting user has permission to access THAT specific resource. GET /api/users/123/documents — does it verify the caller is user 123 or an admin?
Function-level authorization
Admin endpoints must verify the caller has admin privileges. Not just hidden from the UI — actually enforced server-side. Check for endpoints that are "admin only" in the frontend but accessible to any authenticated user.
Field-level authorization
Some fields should only be readable/writable by certain roles. A PATCH /api/users/123 that allows setting role: "admin" if the role field isn't explicitly filtered is an escalation vulnerability.
4. Cryptography
Red Flags in Review
- •Custom encryption or hashing implementations
- •MD5 or SHA1 for password hashing
- •Hard-coded encryption keys or IVs
- •ECB mode encryption (patterns preserved)
What to See Instead
- •Standard library implementations (libsodium, etc.)
- •bcrypt, scrypt, or argon2 with proper work factors
- •Keys from KMS or environment, IVs randomly generated
- •GCM or CBC mode with proper IV handling
5. Error Handling and Logging
Verbose error messages
Stack traces, SQL errors, or internal paths exposed to users leak information attackers use for reconnaissance. Return generic error messages to users; log details server-side.
Sensitive data in logs
Logging request bodies that contain passwords, tokens, credit card numbers, or PII. Log sanitization should strip sensitive fields before writing.
Missing error handling
Unhandled exceptions that crash the application or leave resources in an inconsistent state. In financial applications, a crash during a transaction can lead to fund loss.
The Secure Review Process
Trace the Data
Follow every piece of user input from entry point to final use. Every transformation, every storage, every output. Mark where validation happens (or doesn't).
Check the Boundaries
Identify every trust boundary crossing: user-to-server, server-to-database, server-to-external-API, server-to-filesystem. Verify input validation at each boundary.
Question the Assumptions
What does this code assume about the caller? About the input? About the environment? Are those assumptions enforced or just hoped for?
Think Like an Attacker
For each function, ask: "If I wanted to abuse this, how would I?" Can I skip steps? Provide unexpected types? Call functions in wrong order? Send excessive data?
💡Use a Checklist
Don't rely on memory during security review. Use a checklist. The OWASP Code Review Guide provides comprehensive checklists organized by vulnerability type. Our Smart Contract Audit Checklist follows the same principle for blockchain code — systematic checklists catch what ad-hoc review misses.
Automating What You Can
Manual review is essential but doesn't scale. Augment it with automation:
Layered Code Security
IDE plugins (immediate)
Real-time security linting as developers write code. Catches common patterns like SQL concatenation, hardcoded secrets, and dangerous function usage. Zero friction — developers see issues before they commit.
Pre-commit hooks (before commit)
Secret scanning (detect-secrets, gitleaks) prevents credentials from entering the repository. Format and lint checks catch basic issues.
CI/CD pipeline (before merge)
SAST tools (Semgrep, CodeQL) scan for vulnerability patterns. Dependency scanning (Dependabot, Snyk) checks for known vulnerabilities. As we covered in CI/CD Pipeline Security, these gates prevent vulnerable code from reaching production.
External audit (before release)
Professional security testing for critical releases. Our Web Security Auditor provides automated coverage, and expert review adds manual testing for business logic flaws that tools can't catch.
For Smart Contract Developers
Everything above applies to smart contract code — with higher stakes. Smart contracts are immutable after deployment, handle real money, and execute in an adversarial environment. Security review for smart contracts must also cover:
- Reentrancy patterns (as we detailed in Reentrancy Attacks Explained)
- Precision and rounding issues in financial calculations
- Access control on privileged functions
- Upgrade safety for proxy patterns (covered in Smart Contract Upgradability)
Our Solidity Security Patterns handbook provides the equivalent secure coding patterns for blockchain development.
Want professional eyes on your code? Our Web Security Auditor automates vulnerability detection, and our expert review provides manual code review by security engineers. For smart contracts, our Smart Contract Auditor specializes in blockchain-specific security patterns. Get started.