In one analysis of AI-assisted commits inside Fortune 50 codebases, syntax errors fell 76 percent and logic bugs fell 60 percent between December 2024 and June 2025, exactly the defects a static scanner is built to catch. In the same dataset, privilege escalation paths rose 322 percent and architectural design flaws rose 153 percent, exactly the defects a static scanner is not built to catch, according to Apiiro's analysis of AI-driven development. Read those two trend lines together and the shape of AI-generated code security risk comes into focus: the vulnerability classes are migrating into the category your tools cannot see, while getting cleaner in the category they can.
Why this looks different from a human bug
Traditional code review and static analysis grew up around a specific kind of mistake: a developer forgets to escape output, concatenates a string into a query, hardcodes a credential. These are pattern-matchable. A scanner with a rule for CWE-89 finds unescaped SQL concatenation whether it appears in file one or file ten thousand. AI-generated code does not eliminate that category, but it compresses it, per the Apiiro numbers above, while expanding a category built from something else entirely: implicit assumptions about who is allowed to call what, encoded nowhere a scanner can read.
The volume problem compounds it. GitClear's 2025 analysis of 211 million changed lines of code found the share of edits classified as refactoring fell from about 25 percent in 2021 to under 10 percent in 2024, while copy-pasted code rose from 8.3 percent to 12.3 percent over the same period, the first time in that dataset that copy-paste overtook code reuse through moved lines. More new code, less of it consolidated or re-examined, is exactly the condition under which a reviewer's mental model of the codebase stops matching the actual codebase. I covered the operational side of that gap in vibe coding security; this post is about what specifically breaks and how to test for it.
The vulnerability classes AI-generated code security testing has to cover
Four categories account for most of what actually ships. Two are the kind a scanner is good at. Two are not.
Authorization and access control gaps
Missing or broken authorization, the class MITRE catalogs as CWE-862, is the biggest mover in Apiiro's data: privilege escalation paths up 322 percent. MITRE's own guidance explains why tooling struggles here: it states plainly that "automated static analysis tools have difficulty detecting custom authorization schemes," and rates automated detection effectiveness for this weakness as Limited. An AI assistant does not know your authorization model is role-based in one service and attribute-based in another. It pattern-matches to whatever similar code it has seen, and the result compiles cleanly while skipping a check that only your application's own rules would flag as missing.
Business logic and architectural design flaws
Design flaws rose 153 percent in the same Apiiro dataset. PortSwigger's Web Security Academy explains why these evade automation directly: identifying them "requires a certain amount of human knowledge, such as an understanding of the business domain," which "makes them difficult to detect using automated vulnerability scanners." A checkout flow that accepts a negative quantity, a password reset that can lock out a legitimate account, an API that trusts a client-supplied role field: none of these look wrong to a pattern matcher. They only look wrong once you know what the business rule was supposed to be.
Classic injection and pattern-matchable bugs
This category has not disappeared, and it belongs in the taxonomy so the picture is not lopsided. The original large-scale study of this problem, NYU's "Asleep at the Keyboard?", had GitHub Copilot complete 89 scenarios built from MITRE's Top 25 weaknesses and found roughly 40 percent of the resulting 1,689 programs were vulnerable. These are the bugs SAST is built for, and they still ship, usually because the scan was never run against the AI-authored branch or its findings were dismissed as noise.
Supply chain and dependency drift
AI assistants sometimes recommend packages that do not exist, a risk researchers have called slopsquatting once attackers register the fake names. Even when the package is real, code volume growing faster than dependency review widens the gap between what SCA flags and what anyone actually reads. This is the one class SCA tools are built for. The gap here is process, not detection.
Why static scanning and human review both miss the ones that matter
Every argument above rests on the same mechanism: static analysis reasons about code structure, not application intent. That is not a hypothetical limitation. Charoenwet, Thongtanunam, Pham, and Treude's 2024 empirical study ran real static analyzers against 815 real-world vulnerability-contributing commits across 92 C and C++ projects. A single tool produced a warning inside the vulnerable function in 52 percent of cases, at least 76 percent of those warnings were irrelevant to the actual vulnerability, and 22 percent of the vulnerable commits triggered no relevant warning at all.
Here is the honest concession. That study covers memory-safety-heavy C and C++ code, not the authorization and logic flaws AI-generated code is disproportionately introducing, and a well-tuned SAST, SCA, and secrets-scanning stack still catches real, common problems cheaply: hardcoded keys, known-vulnerable dependencies, straightforward injection. Keep running all of it.
The claim is narrower than "scanners are bad." Scanners are structurally unable to evaluate whether a given code path is reachable by an unauthorized user in your specific application, because that question depends on runtime behavior and business context no static rule encodes.
How to actually test for it
| Control | Catches | Structurally blind to |
|---|---|---|
| SAST | Injection, XSS, hardcoded crypto misuse, known CWE patterns | Authorization logic, business rules, anything requiring app context |
| SCA | Known-vulnerable and hallucinated dependencies | Whether the vulnerable function is reachable in your app |
| Secret scanning | Committed credentials and keys in the diff | Logic and access-control flaws entirely |
| DAST (unauthenticated) | Surface-level injection and misconfiguration on live endpoints | Authenticated, role-specific business logic paths |
| Manual or exploit-based testing | Whether a flagged path is actually exploitable, including auth and logic flaws | Scaling to every commit on its own |
Running all four scanning layers is table stakes, not a strategy. Each closes a different narrow gap, and none of them answer the question that actually matters for AI-generated code: can an authenticated but unauthorized user reach this path and do something they should not. Answering that requires testing behavior, not code, which means authenticated dynamic testing and exploit validation against the running application, not another static rule set. Application security best practices for 2026 covers where this sits inside a full program, and web security best practices and our DevSecOps field guide cover the adjacent pipeline controls.
Concretely, that testing means crawling the application with at least two authenticated sessions, a low-privilege account and a higher-privilege one, then attempting to reach the higher-privilege account's objects and functions from the low-privilege session. A path that returns data or executes an action it should not is a proven authorization flaw, not a suspected one. That is a different exercise from running a scanner against a diff, and it is the one that actually answers the question SAST, SCA, and secret scanning structurally cannot.
What this means for your team
If your AppSec program was built around static findings and human review, AI-generated code security needs a different question at the top of the list. The question is not whether the scanner flagged anything. It is which of these code paths you actually proved is exploitable. That reprioritization matters most on authorization and logic-heavy surfaces, the exact ones the Apiiro data says are growing fastest, and the exact ones every control in the table above is weakest against.
Practically, that means budgeting time for authenticated dynamic testing on every release that touches an authorization boundary, not only before a compliance audit. It also means treating any AI-authored change to access control, session handling, or a payment path as security-critical by default, whether a person or a model wrote the diff. The tool that flags the most findings is not the one that matters. The one that proves which findings are real is.
From taxonomy to proof
Vortex exists for exactly the gap this taxonomy maps. Instead of adding another static rule set, Vortex tests the running application the way an attacker would: it maps whether a given authorization or logic path is actually reachable, and validates that the finding is real rather than theoretical. Then it does the part scanners and validation-only tools leave to you, and the part that matters most when a model wrote the code: it generates the fix for the proven finding and retests to confirm the path is closed. Test, validate, fix, retest, prove, run against the exact vulnerability classes this taxonomy shows scanners cannot see, and closed in the same loop that finds them.
If your team is shipping AI-generated code faster than your scanners can meaningfully cover it, Get a Demo and see the exploitable paths proven, fixed, and re-proven against your own application.
Detect. Defend. Deter.
