Strobesstrobes
Platform
Solutions
Resources
Customers
Company
Pricing
Book a Demo
Strobesstrobes

Strobes connects every exposure signal to autonomous action, so security teams fix what matters, prove what works, and stop chasing noise.

Book a DemoTalk to an expert
ISO 27001SOC 2CREST
  • Platform
  • Platform Overview
  • Agentic Exposure Management
  • AI Agents
  • Integrations
  • API & Developers
  • Workflows & Automation
  • Analytics & Reporting
  • Solutions
  • Exposure Assessment (EAP)
  • Attack Surface Management
  • Application Security Posture
  • Risk-Based Vulnerability Management
  • Adversarial Exposure Validation (AEV)
  • AI Pentesting
  • Pentesting as a Service
  • CTEM Framework
  • By Industry
  • Financial Institutions
  • Technology
  • Retail
  • Healthcare
  • Manufacturing
  • By Roles
  • CISOs
  • Security Directors
  • Cloud Security Leaders
  • App Sec Leaders
  • Resources
  • Blog
  • Customer Stories
  • eBooks
  • Datasheets
  • Videos & Demos
  • Exposure Management Academy
  • CTEM Maturity Assessment
  • Pentest Health Check
  • Security Tool ROI Calculator
  • Company
  • About Strobes
  • Meet the Team
  • Trust & Security
  • Contact Us
  • Careers
  • Become a Partner
  • Technology Partner
  • Partner Deal Registration
  • Press Release

Weekly insight for security leaders

CTEM research, agentic AI trends, and what's actually moving the needle.

© 2026 Strobes Security Inc. All rights reserved.

Privacy PolicyTerms of ServiceCookie PolicyAccessibilitySitemap
Back to Blog
Secure Code Review: A Complete Guide
Application Security

Secure Code Review: A Complete Guide

Shubham JhaMarch 6, 20268 min read

Table of Contents

  • What is secure code review?
  • Manual review vs SAST: which do you need?
  • How does tainted data flow analysis work?
  • Which language-specific sinks should you hunt for?
  • How do you run a code review at pull-request time?
  • How do you handle false positives?
  • Frequently asked questions
  • Sources and references

Authors

S
Shubham Jha

Share

Table of Contents

  • What is secure code review?
  • Manual review vs SAST: which do you need?
  • How does tainted data flow analysis work?
  • Which language-specific sinks should you hunt for?
  • How do you run a code review at pull-request time?
  • How do you handle false positives?
  • Frequently asked questions
  • Sources and references

Authors

S
Shubham Jha

Share

TL;DR
  • ✓Secure code review reads source for security defects before runtime, catching bugs that black-box testing misses because the logic is right in front of you.
  • ✓A strong review pairs automated SAST (Semgrep, CodeQL, SonarQube) for breadth with manual review of the high-risk sinks the scanners flag or miss.
  • ✓The core mental model is tainted data flow: untrusted sources reaching dangerous sinks without sanitization in between.
  • ✓Language-specific sinks (eval, unsafe deserialization, SQL string concatenation, command exec) are where most exploitable bugs live.
  • ✓Reviewing at pull-request time on the changed diff is cheaper and more accurate than periodic full-repo audits.

Secure code review is reading source code specifically to find security defects: injection, broken auth, unsafe deserialization, secrets, and logic flaws that let an attacker do something they shouldn't. Unlike a dynamic test that pokes a running app from outside, code review gives you the logic directly, so you can trace exactly how untrusted input flows to a dangerous operation.

This guide covers how to run a review that actually finds bugs: where automated SAST helps and where it lies, the source-to-sink model that organizes the whole exercise, the language-specific sinks worth grepping for, and how to triage results so your team trusts the output instead of muting it.

What is secure code review?

Secure code review is the practice of examining application source code to find and fix security vulnerabilities before they reach production. It sits in the build/test phase of the SDLC and complements dynamic testing rather than replacing it.

The advantage is coverage of code paths a black-box tester would never reach: an injection sink behind a feature flag, an authorization check that's missing on one of forty endpoints, a deserializer that only fires for admin uploads. Because you read the logic directly, you catch the bug without having to guess the input that triggers it. The OWASP Code Review Guide formalizes this into a repeatable process built around risk, not line-by-line reading of every file. For where it fits among other assessment types, see our overview of the OWASP Top 10 application vulnerabilities.

A secure code review pass, end to end
1
Scope
Identify the app, languages, frameworks, and the highest-risk modules (auth, payments, file handling).
2
Threat map
List trust boundaries and where untrusted input enters: routes, uploads, queue consumers, third-party callbacks.
3
Automated SAST pass
Run Semgrep or CodeQL across the codebase to surface dangerous sinks and taint flows fast.
4
Manual review of high-risk sinks
Read the code around each flagged sink plus auth, crypto, and deserialization the tool may miss.
5
Triage and report
Confirm true positives, drop false positives, rate severity, and file fixes with reproducible context.

Manual review vs SAST: which do you need?

You need both. SAST (static application security testing) gives you breadth and consistency across a large codebase fast; manual review gives you the judgment that tools lack, especially for business logic, authorization, and chained issues. Treat the scanner as a first pass that narrows where you spend human attention.

SAST tools each have a personality. Semgrep uses lightweight pattern rules that read almost like the code itself, so it's fast to write custom rules and great in CI. CodeQL models code as a queryable database and does real interprocedural data-flow analysis, which makes it strong at tracing taint across functions and files. SonarQube blends security rules with code-quality and maintainability checks, which suits teams that want one gate for both.

  • Tools win at: known dangerous functions, hardcoded secrets, missing flags, broad coverage of every file.
  • Humans win at: authorization logic, multi-step business flows, trust assumptions, and judging whether a flagged path is actually reachable.

How does tainted data flow analysis work?

Taint analysis tracks untrusted data from where it enters the application (a source) to where it's used in a dangerous operation (a sink), checking whether anything sanitizes it along the way. If tainted data reaches a sink unsanitized, you likely have a vulnerability.

Sources are anything an attacker controls: request parameters, headers, cookies, JSON bodies, file uploads, message-queue payloads, and data read back from a database that was itself attacker-influenced. Sinks are operations where that data does damage: a SQL query, an OS command, an HTML response, a file path, a deserializer. The space in between is the sanitizer: parameterized queries, output encoding, allow-list validation, safe APIs. CodeQL and Semgrep both model this directly, so you can write a rule that says "flag any flow from an HTTP parameter to Runtime.exec with no escaping." When you review manually, you're running the same algorithm in your head: find the sink, walk backward to the source, and look for the missing sanitizer.

Strobes insight
The scanner's job is to point you at sinks, not to make the call. Every high-severity finding still needs a human to confirm the source is attacker-controlled and the sanitizer is truly missing.

Which language-specific sinks should you hunt for?

Most exploitable bugs cluster around a small set of dangerous sinks, and they differ by language and framework. Learn the sinks for your stack and you can grep your way to the highest-value findings quickly.

  • SQL injection: string-concatenated queries and f-strings/template literals built from input. Look for "SELECT ... " + userId instead of parameterized queries or an ORM with bound params.
  • Command injection: Runtime.exec, os.system, subprocess with shell=True, child_process.exec, backticks in Ruby.
  • Code evaluation: eval, exec, Function(), pickle.loads, and template engines run in unsafe mode.
  • Unsafe deserialization: Java ObjectInputStream / readObject, Python pickle and yaml.load without SafeLoader, PHP unserialize, .NET BinaryFormatter.
  • Path traversal and SSRF: file paths or outbound URLs built from input. For the request-forgery angle, dynamic testing pairs well with this.

These map cleanly to real-world classes you'll also probe dynamically in a web application pentest, so a finding in review usually predicts a finding in testing.

How do you run a code review at pull-request time?

Run the security review on the diff, in the pull request, before merge. Reviewing only the changed lines plus their immediate context is faster, more accurate, and lands the feedback while the author still has the change in their head.

A practical setup: a SAST scan (Semgrep or CodeQL) runs in CI on every PR and posts findings as inline comments, blocking merge only on high-confidence rules so the gate stays credible. A human reviewer then looks at anything touching auth, crypto, deserialization, file handling, or query building, regardless of whether the tool flagged it. Keep PRs small so the security-relevant change isn't buried in a thousand-line refactor. This is also where AI-assisted review is changing the workflow: the same continuous, per-change model underpins agentic pentesting, which keeps assessment running against every build instead of once a quarter.

How do you handle false positives?

Triage every finding into true positive, false positive, or won't-fix, and tune the ruleset so the false-positive rate stays low enough that developers keep reading the output. A scanner nobody trusts is worse than no scanner, because alerts get blanket-muted.

The most common false positives come from data that looks tainted but is actually constrained: a value already validated against an allow-list, a sink that's safe in context (a parameterized query the tool didn't recognize), or an unreachable path. Resolve them by confirming the source is genuinely attacker-controlled and the sanitizer is genuinely absent. Then make the fix stick: suppress with an inline annotation tied to a reason, write a custom Semgrep rule to encode your framework's safe wrappers, and feed confirmed bugs back as regression rules. Prioritize what's left with severity and exploitability, the same lens you'd apply when reading a penetration testing report.

Frequently asked questions

What is the difference between secure code review and SAST?
SAST is the automated tooling that scans source code with static rules; secure code review is the broader human-led process that uses SAST as one input. SAST gives breadth and consistency, while manual review adds judgment for business logic, authorization, and reachability that tools handle poorly.
What are sources and sinks in code review?
A source is any point where untrusted, attacker-controllable data enters the application, such as a request parameter, header, or file upload. A sink is a dangerous operation where that data can cause harm, like a SQL query, an OS command, or a deserializer. A vulnerability exists when data flows from a source to a sink without proper sanitization.
Which tool is best for secure code review, Semgrep or CodeQL?
Semgrep is faster to adopt and great for custom rules and CI gating because its patterns read like the code itself. CodeQL does deeper interprocedural data-flow analysis, making it stronger at tracing taint across functions and files. Many teams run both, plus SonarQube when they want quality and security in one gate.
When in the SDLC should code review happen?
Run the security-focused review at pull-request time on the changed diff, before merge. This keeps feedback cheap and relevant because the author still has context, and it stops vulnerabilities from compounding. Periodic full-repo audits still have a place for legacy code that predates the practice.
How do you reduce false positives in a SAST scan?
Confirm each finding by checking whether the source is genuinely attacker-controlled and the sanitizer is genuinely absent, then tune the ruleset. Encode your framework's safe wrappers as custom rules, suppress confirmed false positives with annotated reasons, and only block merges on high-confidence rules so developers keep trusting the gate.
Does secure code review replace penetration testing?
No. Code review reads logic you can't always reach from outside, while penetration testing exercises the running system, including configuration, deployment, and chained exploits. The two find overlapping but distinct issues, so mature programs do both and feed findings between them.

Sources and references

  • OWASP Code Review Guide
  • Semgrep Documentation
  • GitHub CodeQL
  • OWASP Source Code Analysis Tools
S
Shubham Jha
Security Researcher, Strobes
Shubham Jha leads offensive security research at Strobes, focused on web and API exploitation and red team tradecraft.
Tags
Application SecuritySecure Code ReviewSAST

Stop chasing vulnerabilities Start reducing exposure

See how Strobes AI agents validate and fix your most critical exposures automatically.

Book a Demo
Continue Reading

Related Posts

How to Catch Blind Bugs Scanners Miss
Penetration TestingOffensive Security

How to Catch the Blind Bugs Scanners Miss

Out-of-band validation detects blind SSRF, blind SQLi, and out-of-band XXE that return no in-band response. Learn how it works and why it matters.

May 29, 202613 min
5 Vulnerabilities in Every Vibe-Coded App
Application SecurityLLM Security

5 Vulnerabilities in Every Vibe-Coded App

The 5 security flaws AI coding assistants ship by default: missing authz, leaked secrets, weak JWTs, IDOR, eval RCE — with detection queries and fixes for each.

May 29, 202613 min
Threat Modeling Explained: STRIDE and Methodology
Application SecurityVulnerability Management

Threat Modeling Explained: STRIDE and Methodology

Threat modeling finds design flaws before code exists. Learn STRIDE, data flow diagrams, trust boundaries, and how STRIDE compares to DREAD, PASTA, and attack trees.

Mar 21, 20269 min