phptaint 0.2.0

Security-focused PHP lexer, parser, AST, and configurable taint analysis engine
Documentation
# 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.

[![crates.io](https://img.shields.io/crates/v/phptaint.svg)](https://crates.io/crates/phptaint)
[![docs.rs](https://docs.rs/phptaint/badge.svg)](https://docs.rs/phptaint)