Evidence-based PHP security assessment for operators and incident responders.
Website · Online check · Documentation · Sample report
Recorded CLI output, condensed for readability. Full evidence · Recording details · Reproduce this image
php -v cannot tell you whether every PHP build on a host is safe. A distribution may backport a fix without changing the upstream version. A hosting panel may carry a second installation. A worker may still be running code that was replaced on disk.
Bastion connects discovery, patch evidence and intrusion indicators in one local workflow. It reports the reason behind each assessment and preserves unknown when the available evidence is insufficient.
The current bundled advisory database covers PHP2Shell, tracked as CVE-2026-109618 and CVE-2026-109619. See the advisory data and its primary sources for the exact coverage. Bastion is not a general-purpose PHP dependency scanner.
Current status: pre-release. There is no published binary release yet. Build from source on Linux or macOS with Go 1.24 or later and Make:
git clone https://github.com/BastionPHP/Bastion.git
cd Bastion
make build
./bastion versionChoose the workflow you need:
# Discover PHP builds and assess their patch state.
sudo ./bastion scan
# Inspect web roots, persistence locations and logs for intrusion indicators.
sudo ./bastion trace
# Combine both into an offline HTML report.
sudo ./bastion report -o bastion-report.htmlStart without sudo if you only need to inspect files your account can read. Elevated access improves coverage of other users' processes, container filesystems and system logs. Use scan --no-exec to disable the php -v and container-exec fallbacks; image export still uses the container runtime CLI.
For a quick version or package assessment, use the browser-based check. Input is evaluated in the browser; it does not inventory your server. Windows users can use this check without installing the CLI.
| Command | What it answers | What you get |
|---|---|---|
scan |
Which PHP builds are present, and what proves their patch state? | Paths, versions, package evidence, running processes, mitigation checks |
trace |
Are there observable signs of an intrusion? | File signatures, persistence findings, log indicators and a timeline |
report |
How can I review or hand off the investigation? | One self-contained HTML file combining scan and trace |
check |
What can be inferred from pasted version or package output? | A focused assessment using the same advisory rules |
More workflows: images, offline filesystems and machine-readable output
# Inspect locally available container images without starting them.
sudo ./bastion scan --images
# Inspect a mounted filesystem instead of the running host.
sudo ./bastion scan --sysroot /mnt/server
# Export evidence for scripts and security tooling.
sudo ./bastion scan --format json > scan.json
sudo ./bastion scan --format sarif > scan.sarif
# Assess one pasted version string.
printf '%s\n' 'PHP 8.3.6' | ./bastion check
# Inspect the flags supported by your build.
./bastion scan -hJSON reports use versioned schemas: bastion.scan/v1 and bastion.trace/v1. SARIF output uses version 2.1.0. Exported reports can include hostnames, paths and matching snippets.
The engine evaluates upstream releases, distribution package versions, vendor rebuild dates, changelog markers and patch fingerprints. Findings include the evidence that contributed to the decision. The decision engine and architecture guide are available for inspection.
| Verdict | Interpretation |
|---|---|
fixed |
The available evidence satisfies the advisory's fix criteria. |
vulnerable |
The build matches an affected version or package range. |
likely-vulnerable |
The build appears affected, with incomplete evidence about a possible fix. |
unknown |
The available evidence does not support a reliable determination. |
A patched build is not evidence that an earlier intrusion did not occur. A trace with no findings is not proof that a host is clean. Coverage depends on privileges, readable files, available package metadata and the bundled advisory database.
| Surface | Discovery and evidence |
|---|---|
| System packages | Debian/Ubuntu, RPM-based distributions and Alpine package metadata; vendor-specific fix data where available |
| Hosting panels | BaoTa/aaPanel, cPanel, CloudLinux and Plesk installation paths |
| Other installations | Remi, LiteSpeed, Homebrew, XAMPP, Bitnami and common source-build locations |
| Containers and images | Docker/Podman containers, readable process namespaces and exported local images |
| Running code | PHP workers, Apache modules and replaced binaries still mapped by a process |
| Intrusion indicators | Webshell patterns, PHP in upload/image files, configuration hooks, persistence locations and logs |
Discovery support and patch-proof coverage are different. Finding a build does not imply that vendor evidence exists for it. Linux provides the broadest coverage; process namespaces and /proc inspection are Linux-specific. macOS builds do not provide those Linux-only checks.
Inspect the trace and report output
The trace demo uses controlled fixtures. The recording script documents how the example output is produced.
- Inspection, not remediation. Bastion does not patch packages, restart services, remove files or quarantine findings.
reportwrites the output file you request; image scanning uses temporary files. - Local analysis. There is no account, telemetry service or hosted analysis backend. Container commands use your configured Docker/Podman context.
- Explicit uncertainty. Missing evidence remains visible instead of becoming a clean bill of health.
- Reviewable rules. Advisory data and trace signatures are checked into the repository. Go and browser implementations share test vectors.
Exit codes are part of the CLI interface:
| Code | Meaning |
|---|---|
0 |
No affected builds or reportable intrusion indicators |
1 |
A vulnerable/likely-vulnerable build or high-severity intrusion indicators |
2 |
Unresolved patch state or suspicious indicators |
64 |
Invalid command or arguments |
70 |
Operational failure |
make test # go vet, race-enabled unit tests and browser-engine tests
make integration # real PHP/container tests; Docker + root or passwordless sudo
make site-serve # build the CLI and serve the website locallyCI checks Linux/macOS unit tests, cross-compilation, browser parity, website links, installer checks and container integration. It also checks trace rules against a corpus of legitimate PHP projects. See workflow runs for current results; these checks are not an independent security audit.
Start with the architecture guide and contribution guide. Changes to advisory logic need matching Go/browser fixtures; new trace rules need both positive fixtures and false-positive checks.
Current work centers on coverage, evidence quality and reproducible investigations. Patch-package generation, migration assistance and runtime protection remain proposals, not supported features or delivery commitments. See the roadmap.
Found a bug? Open an issue. Found a security vulnerability or a false-safe verdict? Report privately.
Released under the MIT license.
