rennf93 / laravel-guard
Laravel middleware adapter for guard-core-php: maps Illuminate HTTP requests to the guard-core engine and block verdicts back to Laravel responses
Requires
- php: ^8.2
- illuminate/http: ^10.0|^11.0|^12.0
- rennf93/guard-core-php: ^4.3.2
- symfony/http-foundation: ^6.4|^7.0
Requires (Dev)
- phpunit/php-code-coverage: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-14 18:14:44 UTC
README
Laravel middleware adapter for [guard-core-php](https://github.com/Guard-Core/guard-core-php): maps `Illuminate\Http\Request` objects to the guard-core engine and translates block verdicts back to Laravel-native responses. Works with Laravel 10, 11, and 12.
Website · Docs · Playground · Dashboard · Discord
Ecosystem
Guard Core is the Python engine. Framework adapters are thin wrappers that translate native request/response types into Guard Core's protocols. The telemetry agents ship security events and metrics to the monitoring backend. Parallel engine implementations exist for Go, PHP, TypeScript (on npm), and Rust (on crates.io) - all ports of the same reference semantics, conformance-tested against the shared adversarial corpus.
Python
| Package | Role | PyPI |
|---|---|---|
| guard-core | Framework-agnostic security engine | |
| guard-agent | Telemetry agent | |
| fastapi-guard | FastAPI / Starlette adapter | |
| flaskapi-guard | Flask adapter | |
| djapi-guard | Django adapter | |
| tornadoapi-guard | Tornado adapter |
Go
Go modules published via GitHub releases. Production-ready.
| Package | Role | Release |
|---|---|---|
| guard-core-go | Go engine | |
| nethttp-guard | net/http adapter | |
| gin-guard | Gin adapter | |
| echo-guard | Echo (v4) adapter | |
| fiber-guard | Fiber (v3) adapter | |
| guard-agent-go | Telemetry agent |
PHP
Published on Packagist under the rennf93 vendor. Production-ready.
| Package | Role | Packagist |
|---|---|---|
| guard-core-php | PHP engine | |
| laravel-guard | Laravel adapter | |
| symfony-guard | Symfony adapter | |
| psr15-guard | PSR-15 adapter | |
| slim-guard | Slim 4 adapter | |
| guard-agent-php | Telemetry agent |
TypeScript / JavaScript
Published under the @guardcore npm scope; source in the guard-core-ts monorepo. Production-ready.
| Package | Role | npm |
|---|---|---|
| @guardcore/core | Core engine | |
| @guardcore/express | Express adapter | |
| @guardcore/nestjs | NestJS adapter | |
| @guardcore/fastify | Fastify adapter | |
| @guardcore/hono | Hono (edge) adapter | |
| guardagent | Telemetry agent |
Rust
Published on crates.io. Production-ready.
| Package | Role | crates.io |
|---|---|---|
| guard-core-engine | Core engine crate | |
| guard-core-rs | Facade crate (consumer entry point) | |
| actix-guard-rs | Actix Web adapter | |
| axum-guard-rs | Axum adapter | |
| tower-guard-rs | Tower adapter | |
| rocket-guard-rs | Rocket adapter | |
| guard-agent-rs | Telemetry agent |
AI Coding Agents
| Package | Role | PyPI |
|---|---|---|
| guard-core-mcp | MCP server: config validation, docs search, detection sandbox |
Features
- The full guard-core-php engine pipeline over Laravel requests: rate limiting, IP lists, payload inspection, security headers
- Lifecycle integration with Laravel's middleware stack
- Configurable behavior notes for passive preview
Documentation
📚 Documentation - full technical documentation for this package.
🛡️ Guard Core - the engine's reference documentation.
🤖 Monitoring Agent Integration - monitor your Guard instance with a monitoring agent.
Install
composer require rennf93/laravel-guard
Usage
Bind the middleware in the container and register it globally:
use Illuminate\Http\Request; use RenzoFranceschini\GuardCore\Config\SecurityConfig; use RenzoFranceschini\GuardCore\Engine\GuardEngine; use RenzoFranceschini\GuardCoreLaravel\GuardMiddleware; // In a service provider (or any container binding) $this->app->bind(GuardMiddleware::class, function () { $config = new SecurityConfig( enableRedis: false, blacklist: ['192.0.2.0/24'], rateLimit: 100, rateLimitWindow: 60, enableRateLimiting: true, ); return new GuardMiddleware(new GuardEngine($config)); });
// Laravel 11/12, bootstrap/app.php ->withMiddleware(function (Middleware $middleware) { $middleware->prepend(GuardMiddleware::class); });
// Laravel 10, app/Http/Kernel.php protected $middleware = [ // ... \RenzoFranceschini\GuardCoreLaravel\GuardMiddleware::class, ];
Blocked requests get the engine's block verdict translated exactly (status, body, headers) as an Illuminate\Http\Response: 403 Forbidden for a blacklisted IP, 429 Too many requests with Retry-After for a rate limit hit.
Pass-through responses are finished by the middleware too: the engine's security headers and CORS verdict headers are merged on top of the handler's response, and the engine's behavioral return rules observe the response status code plus a body prefix bounded by behaviorMaxResponseBodyInspectBytes (only while behaviorScanResponseBody is on). Per-route configuration attaches through the middleware's route map or a custom resolver:
use RenzoFranceschini\GuardCore\Routing\RouteConfig; use RenzoFranceschini\GuardCoreLaravel\GuardMiddleware; return new GuardMiddleware( new GuardEngine($config), routes: [ '/docs/' => new RouteConfig(enableSuspiciousDetection: false), '/api/' => new RouteConfig(rateLimit: 5, rateLimitWindow: 10), ], // optional: country resolver for RouteConfig geoRateLimits tiers geoRateLimitResolver: $myResolver, // optional: custom resolver receiving the Illuminate request routeResolver: fn (Request $r) => $r->is('admin/*') ? new RouteConfig(bypassedChecks: ['rate_limit']) : null, );
routes patterns match a path exactly or as a prefix when they end with /. Geo rate-limit tiers need a country resolver: pass geoRateLimitResolver explicitly, or configure geoIpHandler together with blockedCountries/whitelistCountries (the engine keeps the injected handler only when country lists are set) and the middleware bridges it onto the engine's rate-limit handler automatically.
Lifecycle
PHP shared-nothing applies: construct GuardEngine (and therefore GuardMiddleware) per request in classic FPM, or per worker under Octane/FrankenPHP. The middleware holds no mutable state of its own. In-memory fallbacks are per-request safety nets; distributed rate limits, IP bans, and cloud-range caches require Redis (set enableRedis: true and point REDIS_HOST/REDIS_PORT at your instance).
Behavior notes
- Fail-closed: if the engine throws, the middleware returns the engine's fail-closed response (
500 Security check failed, honorably overridden bycustomErrorResponses) instead of letting the request through. - Bounded body read: the request body is scanned as a prefix of at most 256 KiB (
LaravelGuardRequest::MAX_BODY_BYTES, matching the engine's full-scan window). The framework materializes the full body in memory; the engine only ever sees the capped prefix. Payloads beyond the prefix, or signatures split across its boundary, are not detected. - Client address: the adapter maps the engine's
clientHost()onto$request->ip(). Without Laravel's TrustProxies middleware that is the connectingREMOTE_ADDR, and the engine's owntrusted_proxies/X-Forwarded-Forresolution applies. With Laravel's TrustProxies configured, Laravel resolves the forwarded chain first and the engine sees the resolved client. Pick one side to do the resolving; configuring both can double-hop. - With
redisFailOpen: truethe middleware constructs and serves requests even when Redis is unreachable; withredisFailOpen: falseconstruction fails closed. - No security headers or CORS are added by this adapter. (Laravel/Symfony response mechanics put a
Dateand a privateCache-Controlon every response object; the engine's own headers are copied exactly.)
Testing
composer lint
composer test
composer test runs the plain-PHP suite in bin/test_laravel.php (unit coverage always; set REDIS_HOST to a reachable Redis to include the shared-state integration cases).
Status
Released: v1.1.0 on Packagist. The engine floor is rennf93/guard-core-php ^4.1.0; no 4.1.0 of the engine is currently published (its tag is absent and Packagist's latest is v4.0.4), so public resolution is collapsed until the synchronized 4.2.0 train retags the engine - CI resolves the engine from the master sibling checkout in the meantime.
License
MIT