Taint analysis follows untrusted data through a program and flags any
path on which it reaches a dangerous operation unsanitized. The
sources are where it enters: an HTTP parameter, a request body, a
file. The sinks are where it would do damage: a SQL query, a shell
command, eval, a file path, an outbound URL. A sanitizer on the
path between them clears the taint: escaping, a parameterized query,
allow-list validation. It is the core technique behind
injection-vulnerability detection. The model underneath is
information-flow security — ultimately non-interference, the
property that untrusted inputs must not influence trusted operations
(Sabelfeld and Myers 2003)1.
Static and dynamic¶
Two forms answer the same source→sink question. Static (SAST) traces taint through the code without running it — a specialization of static analysis built on interprocedural dataflow rather than a linter's one-file-at-a-time pattern matching (like dead-code detection). It finds paths the tests never exercised, at the cost of false positives on infeasible paths and unmodeled sanitizers.
Dynamic taint tracking instruments the running program instead, so it sees real execution and reports far fewer false positives, but only along the paths the traffic actually drives. This is the engine under IAST (interactive application security testing); RASP is the production-time counterpart, blocking a tainted flow instead of reporting it.
Sources, sinks, and sanitizers¶
The analysis is only as good as its model of sources, sinks, and sanitizers. A missing source or sink is a silent blind spot; a sanitizer the tool doesn't recognize is a false positive. Tuning them for a codebase and its frameworks is the work of applying the method.
What it catches¶
- Injection flaws. SQLi, command injection, XSS, path traversal, SSRF, unsafe deserialization — anywhere external input reaches a dangerous operation along an unsanitized path.
- Cross-procedure flows. Taint that passes through several functions, a field, or a collection between source and sink — which a local pattern rule cannot see.
What it does not catch reliably: implicit (control-flow) flows, where a value leaks through which branch ran rather than through an assignment — most production tools ignore these, and tracking them soundly is the hard part of information-flow security (Sabelfeld and Myers 2003)1. And nothing outside the configured source/sink/ sanitizer sets.
Tools¶
Static (SAST):
- Multi-language: CodeQL and Semgrep run interprocedural source→sink queries across many languages.
- Python: Pysa (Meta).
- Hack: Zoncolan (Meta).
- Node.js: the research tool ODGen (Li et al. 2022)2 builds an object dependence graph by abstract interpretation and queries it for source-to-sink flows, which reaches prototype-pollution chains specific to the npm ecosystem.
Dynamic:
- Binary: Triton does dynamic taint for analysis and reverse engineering.
- Node.js: the open-source Augur (Aldrich et al. 2022)3 does dynamic taint tracking that follows JavaScript's asynchronous control flow.
- IAST: largely commercial (Contrast, Seeker), an agent that runs inside the app alongside a functional or DAST suite.
When to use, when not¶
Use:
- Web and service code with a clear untrusted-input surface — the static form belongs in CI as a security gate on every diff.
- Adding the dynamic form when a SAST tool's false-positive volume is unworkable and a functional or DAST suite is already exercising the code, so findings are confirmed against real execution.
Don't:
- Treat a clean run as proof. Mainstream engines trade soundness for scale and a low false-positive rate.
- Lean on the dynamic form for coverage: it only sees what the exercising traffic reaches, like any runtime observation.
Evidence¶
- At scale. Meta runs taint analysis across its codebases — Zoncolan on Hack, Pysa on Python — as a routine diff-time security gate.
- On a package ecosystem. ODGen reported 180 previously-unknown vulnerabilities in npm packages, 70 of which received CVE identifiers (Li et al. 2022)2.
Classification¶
- Quality dimensions: Security, Functionality.
- Area: Injection-class vulnerabilities — untrusted input reaching SQL, shell, eval, a file path, a URL fetcher, a deserializer; web and service code, security review of any language with a source→sink surface.
- Guarantee: Empirical.
Referenced by¶
- Agent security testing · Methods
- Deep static analysis · Methods
- Schema and boundary validation · Methods
- Static analysis · Methods
- Choosing methods · Overview
References¶
-
Sabelfeld, Andrei, and Andrew C. Myers. 2003. "Language-Based Information-Flow Security." IEEE Journal on Selected Areas in Communications 21 (1): 5–19. https://doi.org/10.1109/JSAC.2002.806121. ↩↩
-
Li, Song, Mingqing Kang, Jianwei Hou, and Yinzhi Cao. 2022. "Mining Node.js Vulnerabilities via Object Dependence Graph and Query." Proceedings of the 31st USENIX Security Symposium (USENIX Security 2022), 143–60. https://www.usenix.org/system/files/sec22summer_li-song.pdf. ↩↩
-
Aldrich, Mark W., Alexi Turcotte, Matthew Blanco, and Frank Tip. 2022. "Augur: Dynamic Taint Analysis for Asynchronous JavaScript." Proceedings of the 37th IEEE/ACM International Conference on Automated Software Engineering (ASE 2022), 153:1–4. https://doi.org/10.1145/3551349.3559522. ↩