primedefender / php
PrimeDefender security middleware for PHP: WAF-style detection, blocking, and incident reporting to the PrimeDefender bridge.
Requires
- php: >=8.1
- psr/http-factory: ^1.0
- psr/http-message: ^1.0 || ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
None
Suggests
- nyholm/psr7: PSR-7 implementation for Slim/PSR-15 apps
- slim/slim: Use Middleware with Slim
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-09-19 00:44:49 UTC
README
PrimeDefender adds a security layer to PHP apps (plain PHP, Slim, or any PSR-15 stack): it inspects incoming requests for common attack patterns, optionally blocks them, and sends structured incidents to your PrimeDefender bridge (for example for a live monitoring map).
This package is the PHP counterpart of primedefender-client (Node.js) and primedefender-fastapi (Python).
Features
| Detection | Notes |
|---|---|
| SQL injection | Signature-based |
| XSS | Signature-based |
| Brute force | Configurable window on auth paths |
| Path traversal | Signature-based |
| Command injection | Signature-based |
| File inclusion | Signature-based |
| DDoS / flood | Per-IP sliding window |
| Bot activity | User-agent heuristics + rate limit |
| Scanner | UA + path probes + rate limit |
| Suspicious request | Method / query / body heuristics |
| Auth bypass probe | Header / query patterns |
| Excessive encoding | Nested percent-encoding depth |
Blocked requests return JSON with HTTP 403 or 429 as appropriate. Incidents are POSTed to the bridge (default path /ingest if your PRIMEDEFENDER_BRIDGE_URL has no path).
Requirements
- PHP 8.1+
- PSR-7 / PSR-15 implementations for middleware mode (e.g.
nyholm/psr7+ Slim) - A running PrimeDefender bridge that accepts the incident JSON
Install
composer require primedefender/php
For PSR-15 middleware (Slim, etc.):
composer require primedefender/php nyholm/psr7 slim/slim
Environment variables
Set these in the environment (or load a .env file before the app starts). PHP does not load .env automatically — use your framework or putenv() / $_ENV.
| Variable | Required | Description |
|---|---|---|
PRIMEDEFENDER_BRIDGE_URL |
Yes* | Bridge base URL, e.g. http://localhost:3000 (path /ingest is added if missing) |
PRIMEDEFENDER_API_KEY |
Yes* | API key sent as X-Api-Key / Authorization: Bearer |
PRIMEDEFENDER_SITE_ID |
Yes* | Site identifier in payloads |
PRIMEDEFENDER_SITE_LAT |
Recommended | Target latitude for map “to” pin |
PRIMEDEFENDER_SITE_LON |
Recommended | Target longitude |
PRIMEDEFENDER_SITE_REGION_LABEL |
Optional | Human label, e.g. Indonesia, Bali → targetLabel = "{site_id} · {label}" |
PRIMEDEFENDER_PRIVATE_SOURCE_LABEL |
Optional | Label for private/loopback IPs |
PRIMEDEFENDER_AUTH_BYPASS_MODE |
Optional | observe or block (default block) |
PRIMEDEFENDER_SUSPICIOUS_REQUEST_MODE |
Optional | observe or block (default block) |
PRIMEDEFENDER_MAX_ENCODING_LAYERS |
Optional | Max nested percent-encoding depth (default 3); deeper chains return 403. Set 0 to disable. |
PRIMEDEFENDER_FLOOD_WINDOW_SECONDS |
Optional | Sliding window for the global per-IP rate (default 10) |
PRIMEDEFENDER_FLOOD_MAX_REQUESTS |
Optional | Max requests per IP per window before 429 / ddos (default 90) |
PRIMEDEFENDER_FLOOD_EXEMPT_PATHS |
Optional | Comma-separated paths not counted toward that limit. If unset, defaults to /health. If set to an empty string, no paths are exempt. |
*If bridge URL, API key, or site id is missing, PrimeDefender is a no-op (detections and reporting stay off).
See .env.example for tuning knobs (PRIMEDEFENDER_BODY_CAP_BYTES, rate limits, GeoIP TTL, per-detection *_MODE / *_ENABLED, etc.).
The bridge URL is configured only via environment variables (.env or server env) — not in code.
Usage
Plain PHP
<?php require 'vendor/autoload.php'; use PrimeDefender\PrimeDefender; // After setting PRIMEDEFENDER_* env vars PrimeDefender::guard(); echo 'hello';
guard() reads the current request from $_SERVER and php://input. If a detection is blocked, it emits JSON and exits.
PSR-15 middleware (Slim 4)
use PrimeDefender\PrimeDefender; use PrimeDefender\Config; use Slim\Factory\AppFactory; $app = AppFactory::create(); $settings = Config::fromEnv(); $app->add(PrimeDefender::middleware($settings, $app->getResponseFactory()));
Same idea as FastAPI:
app.add_middleware(PrimeDefenderMiddleware)
Optional overrides
PrimeDefender::guard([ 'siteLabel' => 'Indonesia, Bali', 'authBypassMode' => 'observe', 'suspiciousRequestMode' => 'block', ]);
siteLabel aliases siteRegionLabel. Mode keys in blocksDetection() use snake_case (ddos, brute_force, etc.).
Explicit settings (tests or multi-tenant)
$settings = Config::fromEnv(); $middleware = PrimeDefender::middleware($settings, $responseFactory);
Config::loadSettings() caches env-based settings; call Config::clearSettingsCache() to reset.
Connect to the PrimeDefender bridge
- Run your bridge (often on port
3000or behind HTTPS). - Set
PRIMEDEFENDER_BRIDGE_URLin.envor server environment, e.g.http://localhost:3000. - Ensure the bridge exposes
POST /ingest(or set the full URL including path). - Use a valid
PRIMEDEFENDER_API_KEYaccepted by the bridge.
Health check (typical): GET http://localhost:3000/health.
Test SQLi / XSS locally
SQL injection (query)
curl "http://127.0.0.1:8010/auth/login?next=' OR 1=1 --"
XSS
curl "http://127.0.0.1:8010/?q=%3Cscript%3Ealert(1)%3C/script%3E"
Map labels (optional test headers)
curl "http://127.0.0.1:8010/auth/login?next=' OR 1=1 --" \ -H "X-Prime-Source-Lat: 34.6937" \ -H "X-Prime-Source-Lon: 135.5023" \ -H "X-Prime-Source-Label: Japan, Osaka"
Examples
examples/plain.php— minimalPrimeDefender::guard()scriptexamples/slim.php— Slim 4 middleware setup
License
MIT — see LICENSE.