Blog

What AI security code review actually catches on every PR

Six concrete finding categories the AI security code review pass surfaces on every pull request — auth, secrets, injection, unsafe deserialization, dependency risk, and severity-graded findings — paired with the cross-link into /security and the path:line evidence the second pass anchors to.

· 6 min read

AI security code review, automated PR security review, and dependency vulnerability review name three buyer-intent clusters on /security, and the second one is what most teams actually mean when they say 'we want a security pass on every PR.' It is the same review surface as code review, fired on the same GitHub App webhook, anchored to the same path:line — but tuned to surface six concrete finding categories the second pass emits, severity-graded so the alert the engineer reads has a triaged weight behind it. This post walks those categories, names what each looks like on a real PR, and points at the finding card on /security to show what the surfaced shape looks like in practice.

Auth: missing verification, broken object-level authorization, and implicit-trust paths

The first category the security pass emits is auth, and it is the category most code-only reviews miss by an order of magnitude. The surface looks for missing JWT verification on a route the diff just opened, missing ownership checks on a resource lookup, and the implicit-trust paths that let a request reach data it should not — the kind that surface as object-level authorization holes a rule-bot scores low and a reviewer scores high. Every finding anchors to a concrete path:line in the diff so the security team reads the failing line rather than a generic alert; the catch catalog on /security lays the full shape out and shows the path:line evidence surface in practice.

Related → Six categories the security pass catches on every PR

Secrets: hardcoded keys, leaked tokens, and the rotation cadence the catch hits

The second category is secrets, and the surface scans every diff for credential-looking strings then traces the call sites the credential feeds into. Patterns include the obvious — a literal api_key= in a config file or a base64 blob that decodes to a real key — and the subtle, like a transmitter key fanned out across modules where an env var would have been the right move. Each finding carries the exact path:line so the rotation task has a starting point, and the install-side surface ships the follow-up commit that rotates the key on a sandboxed branch. Field notes on the shift-left surface live in /blog/ai-pr-review-for-security, and the install path is /integrations/github where the GitHub App wiring is documented end-to-end.

Related → shift-left review on the same webhook surface, the GitHub install path

Injection: SQL, command, template, and prompt — the surfaces the reach grades by

The third category is injection, and the second pass specifically hunts user-controlled input reaching a sink — string concatenation into a SQL query, a shell command built from a request param, a template renderer fed unescaped data, or an LLM prompt constructed from user input rather than from a structured prompt template. Reach grades the severity: a public-route injection lands critical because it is reachable and exploitable from outside the trust boundary, while an admin-only template injection lands advisory because the codepath exists but is gated behind a role check the security team owns. Severity is bucketed consistently across the surface, the rule-base stays narrow, and the model flags every variant on the same review surface so the engineer reads the finding rather than chasing it.

Unsafe deserialization: pickle, eval, YAML-without-SafeLoader, and the gadgets they unlock

The fourth category is unsafe deserialization, and many code reviews skip the deserialize-the-bytes side of the data plane because the rule is fuzzy and the gadgets are stack-specific. VeriFlow surfaces the paths where untrusted bytes are decoded into live Python or live JS — pickle.loads on request input, eval or exec feeding a request param, a YAML.load without SafeLoader, a JSON.parse that hands the result straight to a constructor — the gadgets that turn a YAML payload into server-side code execution. Run the same diff past VeriFlow's PR-level review and a SonarQube SAST scan and the comparison is no longer about which catches more; VeriFlow reads the diff in PR-level context (the one-line config change that opens an unauthenticated admin route in front of an existing endpoint) and the side-by-side /compare/sonarqube walks the same comparison in detail.

Related → VeriFlow vs SonarQube, side-by-side on the same review

Dependency risk: new CVEs, abandoned packages, and the manifest changes the pass pins down

The fifth category is dependency risk, and every manifest change in the diff is checked against advisory databases the second pass keeps in mind. A dep added without a pin, a CVE landed mid-week, or a maintainer-handoff signal all reach the review — the same review the security team can audit. The relevant finding shape captures the manifest-line and the version range the dep added, and the security-budget math on /pricing is the line item most teams work through first when they decide how much of the surface to gate behind the Free tier and how much to roll into Team. The install path on /integrations/github is the place where the same review opens the manifest the security team is auditing, so dep reviews ship on the same webhook the security pass already runs on.

Related → security-budget math on plans and pricing, the GitHub install path for dep review

Severity-graded findings: how critical vs advisory land on the same PR

The sixth and last category is severity-graded findings — the bucket every other category lands in once the surface has read the diff and triaged it. Findings are bucketed into one of two severities, critical (reachable, exploitable, on a public route) or advisory (codepath exists but is gated, or the surface is admin-only). When the upstream pass returns no findings, the top-level severity is none; when the pass is unable to run deterministically, the badge is unavailable and never a fabrication. The split is what makes the second pass a review surface rather than a rule-bot — the engineer reads the severity before triaging the finding, and the security team rebuilds the audit trail from the same shape.

The two top-level severities and what each looks like on a PR

Critical lands when the codepath is reachable, exploitable, and on a public route — an SQL injection sink on a public POST handler, a leaked API key in a config the deploy script reads, a missing JWT check on a route that just opened. Advisory lands when the codepath exists but the surface is gated — a YAML.load on an admin-only path, a template injection on a pageload that requires a role, a dep that is unpinned but only on an internal tool surface. When neither applies the top-level severity is 'none' so the security team reads an empty finding card rather than guessing, and when the pass is unable to run deterministically the badge reads 'unavailable' rather than fabricating signal. The actual finding banner on /security#real-finding shows the shape on a real run, including the path:line the agent surfaced.

Join the waitlist

Want this checklist living inside your review queue?

Get early access to VeriFlow’s per-language review config and the AI-assisted first-pass reviewer that ships the fix on every PR. We’ll be in touch when seats open up.

FAQ

Frequently asked questions

Quick answers to the questions engineers ask most often when they set up a pull-request checklist. The questions and answers below ship byte-for-byte to Google as a FAQPage rich-results surface.

What does AI security review actually catch on a pull request?

AI security code review surfaces six concrete finding categories on every pull request: auth (missing JWT verification, broken object-level authorization, implicit-trust paths), secrets (hardcoded API keys, leaked tokens, weakened rotation cadence), injection (SQL, command, template, and prompt), unsafe deserialization (pickle.loads on user input, eval/exec on request data, YAML without SafeLoader), dependency risk (new deps with known CVEs, abandoned packages, unpinned floating versions), and severity-graded findings (critical vs advisory, with the unavailable-bucketed shape when the pass cannot run). Every finding anchors to a path:line in the diff so the engineer reads the failing line rather than a generic alert.

How does secrets detection work in PR review without false positives?

The secrets pass scans every diff for credential-looking strings then traces the call sites the credential feeds into. Patterns include the obvious (a literal api_key= in a config file, a base64 blob that decodes to a real key) alongside the subtle (a hash that resolves to a transmitter key, an env var dropped into a generated binding). Each finding carries the exact path:line so the rotation task has a starting point, and the install-side surface ships the follow-up commit that rotates the key on a sandboxed branch — keeping the catch low-noise because the rotation grows out of the finding rather than from a separate manual queue.

What is the injection review workflow VeriFlow runs?

VeriFlow runs a second-pass injection review that specifically hunts user-controlled input reaching a sink — string concatenation into a SQL query, a shell command built from a request param, a template renderer fed unescaped data, or an LLM prompt constructed from user input rather than from a structured prompt template. Reach grades the severity: a public-route injection lands critical; an admin-only template injection lands advisory. The model runs the same review surface as the code-review pass, anchored to a path:line in the diff so the engineer reads the failing line and the security team audits the same evidence.

How does VeriFlow handle dependency risk on every pull request?

Every manifest change in the diff is checked against advisory databases the second pass keeps in mind. A dep added without a pin, a CVE landed mid-week, or a maintainer-handoff signal all reach the review — the same review the security team can audit. The relevant finding captures the manifest-line and the version range the dep added, and the same review opens a follow-up commit that pins the dep or rolls the version forward on a sandboxed branch. The security-budget math and Team-tier gating live on /pricing, and the install path is documented on /integrations/github.

Try it free

See it run on your repo in under 2 minutes