Taint propagation is the quiet discipline that turns a reachable call path into an exploitable one. A call graph tells you that function A eventually calls function B; a taint graph tells you whether an attacker-controlled value in A actually flows into B's arguments. Without the second answer, you cannot responsibly declare a CVE reachable. This post compares how Griffin AI performs taint propagation as part of its grounding and how Mythos-class pure-LLM tools handle the same problem without that foundation.
The problem taint propagation solves
Every serious injection class depends on a taint flow. CWE-89 (SQL Injection) requires untrusted input to reach a SQL execution sink unescaped. CWE-79 (Cross-Site Scripting) requires untrusted input to reach HTML output unescaped. CWE-78 (OS Command Injection) requires untrusted input to reach a shell exec call. CWE-502 (Unsafe Deserialization) requires untrusted bytes to reach an unsafe deserialization function. In each case, the finding only matters if the taint actually makes it from source to sink.
A call path without taint analysis is a necessary condition but not a sufficient one. You can have a reachable call path where every argument is a constant, or a validated enum, or a value that has been passed through a sanitizer before reaching the sink. Treating those paths as reachable floods the queue with false positives. Treating them all as not reachable misses the cases that matter. The only way out is to propagate taint carefully and report the verdict honestly.
Griffin AI's propagation model
Griffin AI builds an explicit taint graph on top of its call graph. Each node is a variable, parameter, or return value; each edge carries the semantics of the data flow: direct assignment, function argument passing, field access, array indexing, destructuring, template interpolation, serialization, and so on. The graph includes source annotations (HTTP request bodies, message queue payloads, file reads of attacker-writable paths) and sink annotations (SQL execution, HTML rendering, shell exec, unsafe deserialization, cryptographic key use, and many more).
Propagation proceeds symbolically through the graph. Griffin tracks which variables hold tainted values, how taint combines when values are concatenated or merged, and how sanitizers break the chain. The output of propagation is not a binary answer; it is a path annotated with each transformation the data undergoes. That level of detail is what allows the LLM's downstream reasoning to be specific about why a finding is real.
The 2026 Q1 Griffin benchmark measured taint-aware precision at 91 percent on a 412-CVE panel, meaning 91 percent of findings marked "reachable with tainted input" were confirmed exploitable by human reviewers. That number is only achievable when taint is tracked end to end; heuristic approaches plateau around 60 to 70 percent.
Mythos-class inference
Mythos-class pure-LLM tools do not propagate taint through a dedicated engine. They infer it from code context, which is a fundamentally different operation. The LLM reads a function and guesses whether its arguments are likely to be attacker-controlled. It reads a sink and guesses whether the incoming data is likely to be sanitized. The guesses are often reasonable, especially for well-known patterns, but they are not verifiable.
The inference approach has three recurring failure modes. First, it loses continuity across function boundaries. When function A calls function B, the LLM often forgets that A's argument was tainted by the time it is reasoning about B. Second, it treats sanitization too permissively. If the code calls something that sounds like a sanitizer (validate, clean, filter), the LLM often assumes it strips taint, even when the implementation does not. Third, it loses precision in loops and recursive structures, where taint can accumulate across iterations in ways the model does not model.
CVE-2023-38545, the curl SOCKS5 heap overflow, is a good example of the kind of flow that inference-only approaches struggle with. The taint has to be tracked across multiple state transitions inside the hostname resolution path. A taint engine with proper flow modeling can capture the flow; an LLM reading curl's source without propagation will see a plausible-looking code path and be unable to say whether the specific attacker condition is reachable.
What the two approaches produce in practice
A Griffin finding on a SQL injection path will name the source (for example, request.body.search_query), the sink (for example, db.query on a specific line), the intermediate variables that carry the taint, and the sanitizers that were or were not applied. If the path has a sanitizer that Griffin recognizes as effective, the finding is suppressed. If the sanitizer is unknown or clearly ineffective, the finding is raised. The LLM's narrative is a summary of verifiable facts the engine has already collected.
A Mythos-class finding on the same code will often look similar in prose but will not reference specific variables along the path; it will describe the pattern rather than the proof. When an engineer tries to confirm the finding, they end up performing the taint analysis by hand. That is not a scalable review process, and it invites the team to either rubber-stamp findings or ignore them.
The sanitization problem specifically
Recognizing sanitizers is one of the hardest parts of taint propagation, and it is where the two approaches diverge most sharply. Griffin maintains an explicit library of sanitizer signatures: framework-provided escapers, parameter binding APIs, allow-list validators, cryptographic primitives, and so on. Each signature names the input and output types and the taint it neutralizes. When the taint engine encounters a sanitizer on the path, it updates the taint state deterministically.
Mythos-class tools try to recognize sanitizers by pattern matching on the LLM side. This works for well-known APIs and fails for custom helpers, for renamed re-exports, and for internal abstractions that wrap sanitizers. Custom sanitizers are extremely common in production codebases, and the false verdicts they generate in pure-LLM tools are a major source of pain for triage teams.
The audit trail
Because Griffin's taint propagation is explicit, the audit trail is explicit. Every finding comes with the path, the taint transitions, and the sanitizer checks. Regulators, auditors, and internal reviewers can verify the claim. With Mythos-class tools, the audit trail is the LLM's prose, which is not a verifiable artifact; a reviewer asking "why did the model say this?" cannot get a structural answer.
How Safeguard Helps
Safeguard surfaces Griffin AI's full taint path for every reachability finding on the console. Each row shows the source, the sink, and the intermediate variables that carry the taint between them, with each sanitizer on the path annotated and classified. When a team wants to accept a finding as a false positive, they have to identify a specific sanitizer or a specific flow break; the UI will not let them dismiss the finding without capturing the reasoning. That discipline produces an auditable queue of decisions. If you are running on inferred taint today and your triage is mostly vibes-based, Safeguard's explicit propagation will restore rigor to the workflow.