phptaint 0.1.1

Security-focused PHP lexer, parser, AST, and configurable taint analysis engine
Documentation
# phptaint

Security-focused PHP lexer, parser, and taint analysis engine with configurable sink registries.

`phptaint` is designed for security tooling rather than full-fidelity PHP compilation. It parses the PHP constructs that matter for taint analysis, tracks flows from superglobals into sinks, supports framework presets, and now loads custom registry rules from TOML.

## Features

- PHP lexer with span tracking
- AST and parser for security-relevant PHP constructs
- Taint analysis across assignments, calls, methods, hooks, and user-defined functions
- Built-in registries for `php_core`, `wordpress`, and `laravel`
- TOML-backed custom sink and sanitizer registry loading
- Support for modern constructs including `match`, `enum`, and `readonly`
- Single-file and multi-file analysis

## Installation

```toml
[dependencies]
phptaint = "0.1"
```

## Quick Start

```rust
use phptaint::{analyze, TaintRegistry};

let findings = analyze(
    "sample.php",
    r#"<?php
$cmd = $_GET['cmd'];
eval($cmd);
"#,
    &TaintRegistry::php_core(),
);

assert!(findings.iter().any(|finding| finding.category == "RCE"));
```

## Modern PHP Constructs

The parser intentionally supports a focused subset of modern PHP that commonly appears in real applications and plugins:

- `match` expressions
- `enum` declarations, including backed enums
- `readonly class` declarations and readonly property modifiers
- nullsafe calls, closures, arrow functions, hooks, and common control flow

Example:

```rust
use phptaint::{analyze, TaintRegistry};

let findings = analyze(
    "match.php",
    r#"<?php
$payload = match($kind) {
    "cmd" => $_GET['cmd'],
    default => "id",
};
eval($payload);
"#,
    &TaintRegistry::php_core(),
);

assert!(findings.iter().any(|finding| finding.category == "RCE"));
```

## Built-In Registries

Use the built-in presets directly:

```rust
use phptaint::{analyze, TaintRegistry};

let source = r#"<?php
$url = $_GET['redirect'];
wp_redirect($url);
"#;

let findings = analyze("plugin.php", source, &TaintRegistry::wordpress());
assert!(findings.iter().any(|finding| finding.category == "Open Redirect"));
```

## TOML Registry Configuration

Custom sinks and sanitizers can now be loaded from TOML with `RegistryFile`:

```rust
use phptaint::{analyze, RegistryFile};

let registry = RegistryFile::from_toml(
    r#"
presets = ["php_core"]
sanitizers = ["safe_template"]

[[sinks]]
function = "render_template"
dangerous_args = [0]
category = "SSTI"
severity = "high"

[[method_sinks]]
object_pattern = "renderer"
method = "render"
dangerous_args = [0]
category = "SSTI"
severity = "critical"
"#,
    "<inline>",
)?
.into_registry()?;

let findings = analyze(
    "custom.php",
    r#"<?php
$tpl = $_GET['tpl'];
render_template($tpl);
"#,
    &registry,
);

assert!(findings.iter().any(|finding| finding.category == "SSTI"));
# Ok::<(), Box<dyn std::error::Error>>(())
```

## Multi-File Analysis

```rust
use phptaint::{analyze_multi, TaintRegistry};

let findings = analyze_multi(
    &[
        ("a.php", "<?php function run_cmd($value) { exec($value); }"),
        ("b.php", "<?php $cmd = $_GET['cmd']; run_cmd($cmd);"),
    ],
    &TaintRegistry::php_core(),
);

assert!(findings.iter().any(|finding| finding.category == "RCE"));
```

## Examples

Run the bundled examples:

```bash
cargo run --example basic
cargo run --example toml_registry
```

## Development

- `cargo fmt`
- `cargo check --all-targets`
- `cargo test`

## License

MIT