# phptaint
Lex, parse, and taint-analyze PHP source code. Tracks data flow from sources ($_GET, $_POST) to sinks (eval, exec, echo) with configurable rules. Ships with WordPress and Laravel presets.
```rust
use phptaint::taint::{TaintRegistry, analyze};
let findings = analyze("plugin.php", r#"<?php
$cmd = $_GET['cmd'];
eval($cmd);
?>"#, &TaintRegistry::php_core());
for f in &findings {
println!("[{}] {} at line {}", f.category, f.description, f.line);
}
```
## Configurable rules
The taint engine is driven by a `TaintRegistry` that defines sinks, sanitizers, and framework hooks. Three presets ship with the crate:
```rust
// PHP builtins only (eval, exec, echo, file ops)
let registry = TaintRegistry::php_core();
// WordPress (adds wp_redirect, $wpdb->query, add_action hooks, esc_html sanitizer)
let registry = TaintRegistry::wordpress();
// Laravel (adds DB::raw, Blade helpers)
let registry = TaintRegistry::laravel();
```
Add your own rules:
```rust
let mut registry = TaintRegistry::php_core();
registry.add_sink("my_dangerous_func", &[], "Custom Vuln", Severity::High);
registry.sanitizers.insert("my_sanitizer".into());
```
## What the parser handles
Assignments, function calls, method calls, static calls, closures, classes, if/else, foreach, while, try/catch, switch, ternary, null coalesce, string interpolation, array literals ([]), nullsafe operator (?->), arrow functions (fn() =>), and WordPress hook callbacks (add_action with inline closures).
It does not handle arithmetic operators, bitwise ops, match expressions, enums, or readonly classes. These don't affect taint flow so they're skipped intentionally.
## Multi-file analysis
```rust
use phptaint::taint::{TaintRegistry, analyze_multi};
let findings = analyze_multi(&[
("a.php", "<?php function run($c) { exec($c); } ?>"),
("b.php", "<?php run($_GET['cmd']); ?>"),
], &TaintRegistry::php_core());
// Detects: tainted data flows from b.php through run() to exec() in a.php
```
## No forced dependencies
secfinding is an optional dependency. phptaint defines its own Severity enum. Enable the `secfinding` feature for From/Into conversions:
```toml
[dependencies]
phptaint = { version = "0.1", features = ["secfinding"] }
```
## Contributing
Pull requests are welcome. There is no such thing as a perfect crate. If you find a bug, a better API, or just a rough edge, open a PR. We review quickly.
## License
MIT. Copyright 2026 CORUM COLLECTIVE LLC.
[](https://crates.io/crates/phptaint)
[](https://docs.rs/phptaint)