padv is a local CLI for discovery, detection, and deterministic validation of PHP security vulnerabilities.
It combines semantic static analysis (SCIP, Joern) with agentic runtime exploitation (LangGraph/DeepAgents) and strict gate-based validation via a Morcilla-instrumented PHP target.
Core philosophy: agents propose and plan; gates decide deterministically based on runtime evidence.
It is designed for local or sandbox targets only. It does not scan external targets, generate advisories, or patch code.
CLI (padv analyze | run | validate)
-> LangGraph state machine (discovery -> synthesis -> validation -> gates)
Discovery: SCIP + Joern (semantic static analysis) + Playwright (web)
Agent stack: DeepAgents (proposer, skeptic, scheduler, experiment)
Runtime oracle: Morcilla instrumentation headers
Validation: Deterministic gates V0-V6 (no LLM in the decision path)
A candidate is only VALIDATED if it passes all six gates (V0-V6). There are no exceptions or overrides.
- Python 3.11+ and uv
- Joern (
joern,joern-parseon PATH) - scip-php (
scip-phpon PATH) - An LLM API key (e.g.
ANTHROPIC_API_KEY) for agentic stages - Morcilla-instrumented PHP target (only for
padv run/padv validate, not needed forpadv analyze)
uv syncRun the CLI without activating a venv:
uv run padv --helpAlternative editable install:
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
padv --helpCreate a local config from the example:
cp padv.example.toml padv.tomlImportant sections in padv.toml:
[target]: target base URL and request timeout[oracle]: Morcilla request/response header contract and API key[store]: output directory, default.padv[auth]: optional login material for authenticated discovery[joern]: Joern execution settings[scip]: SCIP execution settings[llm]: provider/model/API key env[agent]: LangGraph/DeepAgents settings[web]: Playwright-based web discovery settings
Minimum practical setup:
- point
[target].base_urlat your local app - set
[oracle].api_key - ensure
[llm].api_key_envexists in your shell - verify
joern,joern-parse,scip-phpare callable
Example:
export ANTHROPIC_API_KEY=...
uv run padv analyze --config padv.toml --repo-root /path/to/php/repoTo test your own PHP application with padv, follow these steps:
padv requires the Morcilla PHP extension to observe internal function calls and confirm vulnerabilities.
- Build and install the Morcilla extension on your target's PHP environment.
- Ensure the extension is enabled (
php -m | grep morcilla).
The agent uses a SCIP index to understand your project's structure and symbols.
- Install
scip-php. - Run
scip-phpin your repository root:scip-php index
- This generates an index file (usually in
.index/index.scip).
Create a configuration file for your project:
[target].base_url: The URL where your instrumented app is running.[target].repo_root: Local path to your PHP source code.[oracle].api_key: Must match themorcilla.api_keyin your target'sphp.ini.[scip].enabled = true: Ensure SCIP is enabled to provide the agent with high-fidelity grounding.
Start with an analysis run to see what the agent identifies:
uv run padv analyze --config your-project.toml --repo-root /path/to/your/repoTop-level help:
uv run padv --helpCurrent commands:
padv analyzepadv runpadv analyze-failurespadv validatepadv sandboxpadv listpadv showpadv export
Discovery and synthesis only. No runtime validation.
uv run padv analyze \
--config padv.toml \
--repo-root /path/to/php/repoUseful flags:
--mode variant|delta|batch--no-progress--resume [RUN_ID|latest]
Example:
uv run padv analyze \
--config padv.toml \
--repo-root ./targets/mutillidae \
--mode variantFull flow: discovery, research, runtime validation, deterministic gates.
uv run padv run \
--config padv.toml \
--repo-root /path/to/php/repoExample:
uv run padv run \
--config padv.mutillidae.strict.toml \
--repo-root ./targets/mutillidae \
--mode variantValidate existing candidates or analyze a repo and then validate.
Validate already persisted candidates:
uv run padv validate \
--config padv.tomlValidate only selected candidates:
uv run padv validate \
--config padv.toml \
--candidate-id cand-00010 \
--candidate-id cand-00024Analyze and validate in one call:
uv run padv validate \
--config padv.toml \
--repo-root /path/to/php/repoAggregate historical failure patterns from the store.
uv run padv analyze-failures \
--config padv.toml \
--format tableJSON output:
uv run padv analyze-failures \
--config padv.toml \
--format jsonRuns helper commands from [sandbox] in the config.
uv run padv sandbox --config padv.toml status
uv run padv sandbox --config padv.toml logs
uv run padv sandbox --config padv.toml deploy
uv run padv sandbox --config padv.toml resetIf your [sandbox] commands are empty, these are no-ops or fail accordingly.
Inspect stored artifacts.
uv run padv list --config padv.toml candidates
uv run padv list --config padv.toml bundles
uv run padv list --config padv.toml runs
uv run padv list --config padv.toml resumesShow details for one stored object.
uv run padv show --config padv.toml --run-id run-1234abcd
uv run padv show --config padv.toml --run-id run-1234abcd --format text
uv run padv show --config padv.toml --bundle-id bundle-run-1234abcd-cand-00010
uv run padv show --config padv.toml --candidate-id cand-00010Export one bundle to a file.
uv run padv export \
--config padv.toml \
--bundle-id bundle-run-1234abcd-cand-00010 \
--output /tmp/bundle.jsonpadv analyze, padv run, and padv validate emit live progress by default.
Disable it with:
--no-progressInterrupted runs can be resumed:
Resume the latest compatible run:
uv run padv run \
--config padv.toml \
--repo-root /path/to/php/repo \
--resumeResume a specific run:
uv run padv analyze \
--config padv.toml \
--repo-root /path/to/php/repo \
--resume analyze-28062a3a11List resumable metadata:
uv run padv list --config padv.toml resumesBy default, output goes to .padv/.
Important paths:
.padv/candidates.json.padv/static_evidence.json.padv/bundles/.padv/runs/.padv/artifacts/.padv/resume/.padv/langgraph/
Useful things to inspect after a run:
- stage snapshots:
.padv/runs/<run-id>/stages/*.json - run-scoped agent workspace:
.padv/langgraph/<run-id>/workspace/ - persisted summaries and findings:
.padv/artifacts/
-
analyze- does semantic discovery, web discovery, auth setup, research, hypotheses, skeptic, frontier updates
- does not run runtime validation or gates
-
run- does everything in
analyze - then builds validation plans, executes runtime requests, reduces evidence, and runs deterministic gates
- does everything in
-
validate- works on existing candidates or freshly analyzed candidates
- is useful when you want to focus on runtime validation without running the whole research loop again
The repo ships a scanner container.
Files:
Dockerfiledocker-compose.ymlpadv.docker.toml
Example:
docker compose up -d joern
docker compose run --rm padv \
analyze \
--config /workspace/haxor/padv.docker.toml \
--repo-root /workspace/targets/mutillidaeStrict local Mutillidae flow is already wired in this repo.
Relevant files:
scripts/mutillidae_e2e.shdocker-compose.mutillidae.ymlpadv.mutillidae.strict.toml
Bring up and bootstrap the stack:
./scripts/mutillidae_e2e.sh setupRun strict analyze + run against Mutillidae:
./scripts/mutillidae_e2e.sh testCommon reasons a run fails early:
joern,joern-parse, orscip-phpmissing- LLM API key env var missing
- Morcilla target not instrumented, so runtime validation cannot produce oracle evidence
- target base URL wrong or app not reachable
- auth is disabled or unset for an auth-gated target
If discovery succeeds but validation quality is poor, inspect:
.padv/runs/<run-id>/stages/.padv/artifacts/.padv/bundles/.padv/resume/
See CONTRIBUTING.md for development setup, testing, and contribution guidelines.
This project is licensed under the MIT License. See LICENSE for details.