Untrusted input reaches os.system, subprocess, os.popen, eval, exec, or child_process.exec.
Open source, agent-native
Lint-Owl is a static analyzer whose result is the data-flow path from an untrusted source to a dangerous sink. It proves that user input actually reaches the exploit, and shows the exact chain.
This box runs a small taint tracer in your browser, built from the same sources, sanitizers, and sinks as the real analyzer. Edit the code and press Scan to see the path it finds.
Pick a language, load a preset with the buttons (or paste your own code), then press Scan. Each finding is shown as a source-to-sink chain: the line where untrusted input enters, the lines it flows through, and the dangerous sink it reaches. Try the Sanitized (safe) preset to see how a sanitizer clears taint and produces no finding.
runs entirely in your browser, same sources, sanitizers, and sinks as the CLI
Most tools point at a line and say this looks risky. Lint-Owl follows the taint from where it enters to where it detonates.
The CLI prints each finding as a source-to-sink chain and exits non-zero, so it drops straight into CI or a pre-commit hook.
real CLI output. a known sanitizer (int, shlex.quote) on the path clears the taint and the finding disappears
Flag local smells. No data flow across statements, no source-to-sink reasoning.
Matches syntactic patterns. A pattern does not prove the input actually reaches the sink through assignments.
A real dataflow engine, but heavy. Build a database, learn a query language. Overkill for one file.
One small binary whose output is the tainted path itself, and an MCP tool an AI asks "does user input reach this exec".
Each class is just a set of sources, sinks, and sanitizers, so adding one is data, not code. Point --config at a JSON file to add your framework's own.
Untrusted input reaches os.system, subprocess, os.popen, eval, exec, or child_process.exec.
Concatenated input reaches a cursor.execute, executemany, or query call.
Input reaches requests, urllib.urlopen, httpx, fetch, axios, or an http client.
Input reaches open, fs.readFile, or fs.createReadStream without normalization.
Input reaches pickle.loads, yaml.load, marshal.loads, or dill.loads.
int, float, shlex.quote, encodeURIComponent, and friends clear taint, so quoted or cast input is not flagged.
Scan a file or a whole tree of Python, JavaScript, and PHP. Exits non-zero on findings, so it drops into CI or a pre-commit hook.
--sarif emits SARIF 2.1.0 for GitHub code scanning and IDEs. --json gives the raw findings for any other tool.
serve --port 8080 opens a paste-code console and a /scan endpoint that returns the same source-to-sink chains.
The lint_owl_scan tool over stdio, so an agent reviewing a diff can ask "does user input reach a sink here" and get the chain back.
Sanitizer awareness and control-flow and inter-procedural taint are built in. Findings are still candidate paths a human confirms, and that honesty is written into the README.