A static analyzer using AI
Project description
vulnAI
vulnAI is a Python static application security testing tool built around interprocedural taint analysis. It parses Python code, builds function-level summaries, resolves calls across a code graph, and reports source-to-sink vulnerability flows with CWE labels.
It is designed to answer a harder question than simple pattern matching:
Did attacker-controlled data move across functions, returns, aliases, and callsites before reaching a dangerous sink?
Highlights
- Interprocedural taint propagation across function call boundaries.
- Custom codebase indexing, import resolution, call graph construction, CFG construction, use-def analysis, and fixed-point dataflow iteration.
- Per-callsite context isolation to avoid mixing taint from unrelated calls.
- Rule support for common Python web/security vulnerability classes.
- CLI workflow for scanning codebases and scoring OWASP Benchmark Python.
- Measured against OWASP Benchmark Python ground truth and compared with Bandit 1.9.4 on the same supported benchmark scope.
Demo
CLI Scan
vulnai scan ./benchmarks/external/pygoat
Example output shape:
[*] Starting vulnAI scan on: ./benchmarks/external/pygoat
[-] Building CodebaseIndex...
[-] Building CallGraph edges...
[-] Building function summaries...
[-] Running interprocedural taint analysis...
[+] Scan complete.
Vulnerabilities found: 65
Cross-Function Taint Tracking
vulnAI does not stop at the local function. If a value enters through a web request, passes through helper functions, returns into another scope, and then reaches a sink, the analyzer can preserve the flow through the call graph.
def route(request):
name = request.args.get("name")
value = normalize(name)
return render(value)
def normalize(x):
return x.strip()
def render(html):
return HttpResponse(html)
In this shape, the important fact is not just that HttpResponse exists. The
important fact is that attacker-controlled input reached it.
Installation
After publishing to PyPI:
pip install vulnai
From source:
git clone https://github.com/shayaan09/vulnAI.git
cd vulnAI
python -m pip install -e .
Verify the CLI:
vulnai --help
Usage
Scan a Python project:
vulnai scan ./path/to/python-project
Run OWASP Benchmark Python scoring:
vulnai benchmark ./benchmarks/external/OWASPBenchmarkPython ./benchmarks/external/OWASPBenchmarkPython/expectedresults-0.1.csv
Run the local recall corpus:
python ./tests/cwe_recall_check.py --strict
Supported Vulnerability Classes
| CWE | Vulnerability class | Detection style |
|---|---|---|
| CWE-22 | Path traversal | Taint flow |
| CWE-78 | OS command injection | Taint flow |
| CWE-79 | Cross-site scripting | Taint flow |
| CWE-89 | SQL injection | Taint flow |
| CWE-327 / CWE-328 | Weak cryptography / weak hash | Pattern-based |
| CWE-330 / CWE-338 | Insecure randomness / weak PRNG | Pattern-based |
| CWE-502 | Insecure deserialization | Taint flow + sink rules |
| CWE-611 | XML external entity injection | Taint flow + parser rules |
| CWE-798 | Hardcoded credentials/secrets | Pattern-based |
| CWE-918 | Server-side request forgery | Taint flow |
The OWASP Benchmark Python score below uses the 8 currently supported OWASP Benchmark categories: command injection, deserialization, hash, path traversal, SQL injection, weak randomness, XSS, and XXE.
Benchmark Results
Measured on OWASP Benchmark Python using the benchmark's expected-results CSV. The table below reports the supported vulnAI categories only, covering 852 labeled test cases.
| Tool | TP | FP | FN | TN | Precision | Recall | F1 |
|---|---|---|---|---|---|---|---|
| vulnAI | 267 | 50 | 43 | 492 | 0.84 | 0.86 | 0.85 |
| Bandit 1.9.4 | 192 | 50 | 118 | 492 | 0.79 | 0.62 | 0.70 |
Interpretation:
- vulnAI detected 75 more true positives than Bandit at the same false-positive count on the supported OWASP Benchmark Python scope.
- Bandit remains strong on local risky APIs such as
hashlib.md5,random.getrandbits,pickle.loads,eval, andexec. - vulnAI's advantage comes from resolving source-to-sink dataflow across function boundaries rather than only matching local AST patterns.
Reproduce vulnAI's benchmark run:
vulnai benchmark ./benchmarks/external/OWASPBenchmarkPython ./benchmarks/external/OWASPBenchmarkPython/expectedresults-0.1.csv
How It Works
vulnAI runs the scan in phases:
- Parse Python files into ASTs.
- Build a codebase index of modules, imports, functions, classes, and nested definitions.
- Build a code graph with containment, import, call, and external-call edges.
- Build a CFG for each function.
- Run reaching-definition and use-def analysis.
- Build function summaries that describe parameter-to-return and parameter-to-sink behavior.
- Run fixed-point interprocedural taint propagation over the call graph.
- Replay local sink checks once new return taint is discovered.
- Emit CWE-labeled findings with caller, callee, sink, line, and context data.
On OWASP Benchmark Python, the analyzer builds a graph with more than 5,400 nodes, 19,700 edges, and 3,700 indexed functions.
Example Finding
[1] Tainted Flow to Sink: SQL Injection
CWE: CWE-89
Caller: views.search
Callee: database.run_query
Via Parameter: query
Sink Reached: cursor.execute(sql)
Line: 42
Context: views.search -> database.run_query
The goal is to make the report explain both the dangerous operation and how tainted data reached it.
Development
Install in editable mode:
python -m pip install -e .
Run tests:
python -m pytest
Run the positive-only CWE recall matrix:
python ./tests/cwe_recall_check.py --strict
Build the package:
python -m build
python -m twine check dist/*
Project Status
vulnAI is a research/portfolio SAST engine. It is useful for exploring static analysis architecture and catching many common Python vulnerability patterns, but it is not a replacement for a professional security review.
Known limitations:
- Python 3 AST parsing only. Python 2 projects should be converted before scanning.
- Highly dynamic Python features can hide calls or dataflow from static analysis.
- Framework-specific source/sink modeling is rule-dependent and should be expanded over time.
- Benchmark metrics are reported for supported OWASP Benchmark Python categories only.
Responsible Use
Only scan code you own or are authorized to test. Static analysis findings should be reviewed before being treated as confirmed vulnerabilities.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vulnai-0.0.1.tar.gz.
File metadata
- Download URL: vulnai-0.0.1.tar.gz
- Upload date:
- Size: 76.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebe2f37b7efe837b2aa3b1af888f11172af5f103ff2c8e07a53575c64db36905
|
|
| MD5 |
f9624de849a49591b69a8defe073fa3f
|
|
| BLAKE2b-256 |
ccb1a423a37be6de9bf2566fe7ec8e1ee86b654a47c09e857ddca535404038ee
|
File details
Details for the file vulnai-0.0.1-py3-none-any.whl.
File metadata
- Download URL: vulnai-0.0.1-py3-none-any.whl
- Upload date:
- Size: 84.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91c2261fb9daf6b15ce582533b7c9b3311840ca4680dae145e3d11cc25471ff2
|
|
| MD5 |
2d97f6fac07699be0a5218ff2e24378a
|
|
| BLAKE2b-256 |
71fa7d27dc708f4acd56dee45deecc3acf6f5430eef14f999915b73d6e923c37
|