What Is Deep Code Analysis? (And Why SAST + LLM Isn't Enough)
Regex SAST gives you thousands of theory-class findings. LLM-assisted review gives you confident rewrites that may not run. Deep Code Analysis is the third layer: a structural model of your code that proves which findings are real, reachable, and worth fixing.
If you have ever opened a SAST dashboard, scrolled to the bottom of a 12,000-line CSV, and thought “I am never going to triage all of this,” you already understand the problem Deep Code Analysis is built to solve. You also understand why bolting a large language model onto the same regex engine does not fix it.
This guide explains what Deep Code Analysis actually is, why SAST plus an LLM wrapper still leaves you with thousands of unfixable findings, and what changes when you put a structural layer in front of your scanners. If you already know the difference between SAST, DAST, and SCA, skip to the section on what the layer above them all looks like.
The Short Version
Deep Code Analysis is the practice of building a structural model of your application’s hosts, endpoints, parameters, and capabilities — then binding every security finding to a specific point in that model. A finding without a reachability path, a capability class, and a line number is not a finding. It is noise.
This is what separates the practice from legacy SAST and from the “SAST + LLM” wrapper products that flooded the market in 2024–2025. Both are pattern matchers under the hood. One uses regex. The other uses a transformer that summarises the regex output in better English.
Neither answers the only question your security team cares about:
Of the thousands of vulnerabilities my scanner just found, which few of them can an attacker actually exploit against the production code we shipped last Tuesday?
Deep Code Analysis answers that question. Everything else is plumbing.
What SAST Got Wrong
SAST — Static Application Security Testing — has been the workhorse of application security since the early 2000s. The category earned its place. But the engines have not changed much. Most still work like this:
- Parse the source file.
- Apply a set of regular expressions or AST visitors that look for known-bad patterns (
eval,innerHTML,string.format, hardcoded credentials, weak crypto, and a few hundred others). - Emit a finding with a CVSS score, a CWE, a file path, and a line number.
That model has three structural problems that no amount of “AI-enhanced” wrapper can paper over.
Problem 1 — Pattern matchers do not read code
A regex sees eval(input) and flags it. It does not see that input is already sanitised two functions up the call stack. It does not see that this particular branch is only reachable from a configuration endpoint that is bound to localhost. It does not see the guard clause your senior engineer added six months ago.
The result: most SAST findings are unreachable, low-impact, or already mitigated. The interesting flaws — broken object-level authorization, missing rate limits, a business-logic flaw in the new Stripe webhook — are exactly the ones the regex does not match.
Problem 2 — There is no reachability model
A finding on line 117 of src/routes/users.js is meaningless without knowing how user input reaches it, what it does once it arrives, and whether the route is exposed at all.
Legacy SAST stops at the call site. It cannot tell you:
- Which HTTP route serves this function
- Whether the route is exposed publicly or only behind a VPN
- Whether authentication runs before the call site
- Whether the input parameter is actually user-controlled
- Whether the data sink it reaches (a database, a shell, a file) is exploitable from this specific entry point
You get a finding. You do not get a path.
Problem 3 — There is no capability model
Reading a file is not the same as identity obtain. Network reach is not the same as code execution. Reaching a parameterised query is not the same as reaching an unsanitised one.
Legacy SAST collapses these distinctions into a single severity score. It treats every readFile the same way, regardless of whether the file is a static asset or a private key. That makes the priority list useless.
What Bolting an LLM Onto SAST Did Not Fix
In 2024, the obvious answer to SAST noise was to add a large language model. Wrap the scanner in an agent. Have the model summarise the finding, suggest a patch, or rank the findings by “real-world exploitability.”
This helped with one thing: the wall of CSV text became a wall of human-readable summaries. It did not solve any of the three structural problems above. It just made them more legible.
The hard limits are still there:
- LLMs do not reliably execute code. When an LLM “reviews” a snippet, it is pattern-matching on tokens. It does not run the program. It cannot prove the snippet is reachable, only that it looks like the kind of snippet that often is.
- LLMs hallucinate fixes. When asked to patch a vulnerability, an LLM will sometimes rewrite the call site in a way that compiles but no longer matches the original business logic. A human reviewer must catch this. Most teams cannot review every AI-suggested patch.
- LLMs inherit SAST’s blind spots. If the underlying scanner does not see the broken object-level authorization, no amount of post-hoc summarisation will produce it.
The result of the “SAST + LLM” wave was a more confident, more polished, and still ungrounded signal. The auditor still cannot re-run the finding. The developer still does not know whether to trust the suggested patch. The CISO still gets a dashboard full of green checks that mean nothing in production.
This is what created the demand for Deep Code Analysis as a category.
What Deep Code Analysis Actually Is
Deep Code Analysis is a different starting point. Instead of “scan the file for bad patterns,” the question is “what is this application, top to bottom, and what can reach what?”
Concretely, the practice has four shifts:
1. Build a structural model of the application
The first pass walks the entire codebase (and the IaC that defines the runtime) and produces a structural model of the application:
- Hosts — services, serverless functions, third-party APIs
- Endpoints — HTTP routes, gRPC methods, message queue handlers
- Parameters — every input that crosses an endpoint boundary
- Capabilities — what each node can read, write, execute, exfiltrate, escalate
The model is the source of truth. Findings are positions in it, not lines in a file.
2. Bind every finding to a path
When the engine proposes a finding (whether from a pattern, a learned model, or a human-authored rule), it must attach:
- The reachability path — endpoint, parameter, handler, sink
- The capability class — read, write, impersonation, RCE, exfiltration
- The line number — for the human reviewer
A finding without all three is dropped. This is the opposite of legacy SAST, which emits a finding whenever it matches a pattern and leaves path discovery to the human.
3. Verify reachability with an independent pass
This is the critical difference. The engine that proposes a finding is not the same engine that confirms it. A second pass replays the proposed exploit against a sandboxed copy of the target. Only findings that reproduce are kept.
This is the same logic as the scientific method. A claim is not a finding until it survives an independent test.
4. Hand the engineer a reproducible artifact
Every surviving finding ships with evidence an auditor can run, a developer can run, and a CI gate can run. A request, a script, or a sandbox state.
If a finding cannot be reproduced, it is not a finding.
The Audit Trail an Auditor Can Actually Read
The output of Deep Code Analysis is structured for the people who have to defend the work downstream. For each finding, the report includes:
| Field | What it tells the auditor |
|---|---|
| Graph node | Which host, endpoint, parameter |
| Reachability path | The full chain from request to sink |
| Capability class | Read, write, impersonation, RCE, exfiltration |
| Verified by | Which independent pass replayed it |
| Evidence reference | The request, job, or sandbox state to re-run |
| Lines | Exact file path and line number |
| Tainted via | How user input flows through the system |
An auditor reading this can re-run the finding, check the trace, and confirm the severity. They do not have to take the vendor’s word for it.
Why the LLM-Only Tools Cannot Catch Up
The temptation is to assume that as foundation models improve, the “SAST + LLM” wrapper will eventually become equivalent to Deep Code Analysis. It will not, for three reasons:
- LLMs do not build structural models. They consume them as input. Without the upstream model construction step, the LLM is summarising flat text and inventing the path between two nodes.
- LLMs cannot verify their own findings. The verification step requires actually running code against the target. LLMs cannot run code reliably, and their self-consistency checks are weaker than an independent replay pass.
- LLMs hallucinate the business logic. An LLM does not know that
/api/users/:idis supposed to enforce ownership of the record before returning it. The structural model encodes that constraint at the endpoint level. The model cannot infer it from token statistics.
Deep Code Analysis does not replace the LLM. It gives the LLM the structured input it needs to be useful — and gives the engineer the ground truth they need to trust the model’s suggestions.
How Deep Code Analysis Pairs with AI Swarm Pentest
At Plexicus, Deep Code Analysis is the first half of the loop. AI Swarm Pentest is the second. The two together look like this:
- Deep Code Analysis builds the structural model and proposes findings.
- AI Swarm Pentest probes each proposed finding within the agreed scope.
- An independent pass replays the original exploit against the proposed patch and demands evidence.
- Only findings that survive both passes — propose and verify — make it into the report.
What survives is small, accurate, and reproducible. Your team fixes a handful of things instead of triaging thousands. Your auditor re-runs a handful of replays instead of reading a 90-page PDF.
That is the bar. Everything else is noise.
The Practical Question: Is This Just Marketing?
The honest answer is: a year ago, it was partly marketing. The category did not have a name, the products that claimed to do it were wrapping regex engines in LLM summaries, and the proof of “deep” was a longer PDF.
In 2026, the practice has converged on four operational signals:
- The tool can answer “is this reachable?” with a path, not a guess. If your current scanner cannot, it is not doing Deep Code Analysis.
- The tool can answer “what is the capability class?” with a real taxonomy. Not CVSS. Not “high/medium/low.” A capability.
- The tool can produce a reproducible artifact for every surviving finding. Runnable by an auditor, a CI gate, and a developer.
- The tool pairs propose-and-verify. Whatever proposes the finding is not the same thing that confirms it.
If your current stack checks all four, you already have Deep Code Analysis — whether or not the vendor calls it that. If it checks three, you are close. If it checks two or fewer, you have a SAST dashboard with better copy.
Where to Start
If you want to see the difference, you do not need a six-month evaluation. Pick one repository, one branch, one production-like build. Run your current scanner. Count the findings. Then run a Deep Code Analysis pass against the same target. Count the findings that survive independent replay.
The gap between those two numbers is the budget you have been spending on triage that did not need to happen.
Related reading:
- Deep Code Analysis — full product page
- 78% of AI-Generated PRs Contain a Vulnerability — what the actual failure rate looks like in production
- The Autonomous Remediation Playbook — what happens after a finding survives replay