jeffersongoncalves/laravel-scanner-guard
Laravel Scanner Guard detects and blocks vulnerability scanners probing your app for exposed files, admin panels, and known exploit paths. It logs suspicious requests and lets you deny abusive IPs with middleware, helping cut noise and harden your Laravel site with minimal configuration.
database: full audit trail, daily stats, and nginx denylist export — the right default for customer-facing or regulated environments where post-incident review matters.cache: zero-migration, zero-DB adoption for side projects, edge nodes, or services where a short-lived ban is the entire product requirement.http: a satellite/central topology for fleets of Laravel apps that need one consolidated denylist without giving every node database credentials or running aggregation jobs on each.cache driver lowers the cost of trying the package to a config change, which makes "build a bespoke rate-limiter" or "buy a WAF" easier to defer. The http driver is the stronger argument: it converts the package into a lightweight centralized ban bus, a capability usually purchased as a commercial WAF/edge product.scanner-guard:aggregate-and-prune and scanner-guard:export-denylist self-disable with a notice unless the driver is database — a deliberate ops decision that scheduled jobs cannot silently break non-DB deployments. For cache/http teams, that means accepting "no audit trail" as a documented product tradeoff, not a bug to file later.X-Signature over X-Timestamp + body, plus stale-timestamp (403) and replay (409) rejection, means the central app must own secret distribution and clock hygiene. The central store keeps its own salted ip_hash and holds raw IP only in cache — a decision point for privacy reviews and GDPR-style data-minimization positions.ScannerGuard::ban() now returns ?ScannerGuardBan and yields null under cache/http. Any product surface that reads the returned ban model (admin UI, event listeners, audit display) must be specced to handle null; treat this as a minor breaking change when scoping integration work.cache and graduate to http without code changes.Consider adoption when:
http driver is the deciding feature here.cache driver removes migrations entirely.cache, no schema changes, no scheduled jobs, and revisit database if audit requirements appear.http mode and can manage a shared HMAC secret plus synchronized clocks across satellites.Look elsewhere or defer when:
cache and http intentionally produce no local audit trail or stats; only the central app on database has them. If each node must independently retain evidence, stay on database or choose a different tool.ban_duration (e.g., per-process array cache), or eviction under memory pressure would silently shorten bans.To executives: This release removes the package's biggest adoption blocker — the mandatory SQL database — and adds a way to consolidate bans from many applications into one place. In practice that means we can protect small and edge services without standing up a database per service, and we can run a single central denylist feeding every app's nginx export instead of maintaining one per service. It is a low-cost capability expansion on an existing dependency, not a new platform purchase, and it gives us a credible answer to "should we buy a WAF?" for the IP-banning slice of that problem. Main caveats to note: the lightweight modes deliberately keep no audit history, and forwarding is best-effort, so anything compliance-sensitive stays on the database-backed mode.
To engineering: Driver is selected by scanner-guard.driver / SCANNER_GUARD_DRIVER. Default database is unchanged — no upgrade action required beyond adding the new driver and http keys if the config was published. cache needs no migrations and no scheduled jobs; http forwards bans post-response to POST scanner-guard/bans on a central app (enabled via SCANNER_GUARD_HTTP_SERVER_ENABLED=true), signed with hash_hmac('sha256', X-Timestamp.body, secret), with 403 on bad signature or stale timestamp and 409 on replay. The central app records bans like local ones using its own salted ip_hash, keeps raw IPs in cache only, and its nginx export therefore covers all satellites. aggregate-and-prune and export-denylist now no-op with a notice unless the driver is database, so scheduling them is harmless. One contract change to handle: ScannerGuard::ban() returns ?ScannerGuardBan and is null on cache/http — audit any caller that dereferences the result. Watch items: secret distribution and rotation, clock skew versus the timestamp staleness window, and the fact that failed forwards are logged only, with no retry.
How can I help you explore Laravel packages today?