Jayanta Kumar Nath — Updated March 2026
I run a Laravel app that kept getting hit with SQL injection attempts, bot scanners, and random exploit probes. I didn't want to pay for a WAF service, so I built a middleware package that logs everything silently. It doesn't block anything - just watches, logs, and alerts.
After sharing v1.1.0 here and on Reddit, I got some good feedback and spent time hardening it. v1.2.0 is out now with evasion resistance, queue support, and a bunch of fixes.
What It Does
A middleware that sits in your Laravel pipeline, inspects every incoming request against 130+ regex patterns, and logs what it finds. It's a passive detector - it never blocks the request. Think IDS, not IPS.
Detects:
- SQL injection (UNION, blind, stacked queries)
- XSS and script injections
- Remote code execution attempts
- Directory traversal, LFI/RFI
- Scanner bots (SQLMap, Nikto, Burp Suite, etc.)
- DDoS via rate-based detection
- SSRF, XXE, Log4Shell, LDAP injection
What's New in v1.2.0
Evasion Resistance
This was the big one. Regex-based detection is easy to bypass if you know how. Attackers use tricks like:
-
UNION/**/SELECT- SQL comment insertion to break up keywords -
%2527- double URL encoding to sneak past filters -
CHAR(39)- SQL character encoding instead of literal quotes
v1.2.0 adds a normalization layer that strips these tricks before matching patterns. The evasion attempt itself is also flagged separately as high severity. So you get two log entries: one for the evasion technique, one for the actual attack underneath.
Also removed the old SQL Comment Syntax pattern (--, #, /*) - it was the #1 source of false positives. CSS classes like font--bold and CLI flags like --verbose were getting flagged. Real SQL attacks are still caught by the keyword patterns.
Route Whitelisting
New only_paths config - scan only specific routes instead of everything. Useful if you have a high-traffic app and only care about API endpoints or admin routes. Leave it empty (default) to scan all routes.
Queue Support
DB writes and Slack notifications can now be offloaded to a queue. Detection stays synchronous (so nothing is missed), but the write is deferred. Uses a dedicated StoreThreatLog job with 3 retries and backoff.
THREAT_DETECTION_QUEUE=true
THREAT_DETECTION_QUEUE_NAME=default
Auto-Purge
Old threat logs can be automatically cleaned up on a daily schedule.
THREAT_DETECTION_RETENTION=true
THREAT_DETECTION_RETENTION_DAYS=90
ThreatDetected Event
Every confirmed threat dispatches a ThreatDetected event. Hook into it for custom actions - Telegram alerts, SIEM feeds, blocklists, whatever you need.
Other Additions
- Minimum confidence threshold - ignore low-confidence noise (THREAT_DETECTION_MIN_CONFIDENCE)
- API rate limiting - auto-throttle on API routes
- Expanded LFI detection - added phar://, expect://, input:// protocols
- Full RFC 1918 private IP range - fixed 172.16.0.0/12 detection (was only matching 172.16.x.x)
- Localhost SSRF - added 0.0.0.0 to detection
Performance
- Stats queries reduced from 7-9 separate queries to 1 using CASE WHEN aggregation
- Fixed N+1 queries in coordinated attack detection
- Pattern validation cached per process lifecycle
- Content-type aware - skips binary fields in multipart uploads
Security Hardening
- CSV export formula injection prevention
- Log injection prevention (strips control characters)
- SSRF prevention in geo-enrichment (IP validation before external API calls)
- Fixed 3 ReDoS-vulnerable regex patterns
Built-in Dashboard
Dark-mode dashboard with stats cards, 7-day timeline, searchable threat table, top offending IPs, and geo grouping. Uses Alpine.js + Tailwind CDN - no build step.
12 API Endpoints
Full REST API for stats, threat lists, IP rankings, country grouping, timelines, and CSV export. Plug into your own frontend or monitoring stack.
Testing
86 tests, 338 assertions. Includes 16 full-cycle feature tests that send real HTTP requests through the middleware, write to the database, and verify the actual rows - not just unit-level pattern matching.
Installation
composer require jayanta/laravel-threat-detection
php artisan vendor:publish --tag=threat-detection-config
php artisan vendor:publish --tag=threat-detection-migrations
php artisan migrate
Add the middleware in bootstrap/app.php (Laravel 11+):
->withMiddleware(function (Middleware $middleware) {
$middleware->append(\JayAnta\ThreatDetection\Middleware\ThreatDetectionMiddleware::class);
})
Limitations
- Regex-based, not ML - won't catch novel zero-day patterns
- Passive only - detects but doesn't block
- No IP reputation database built in
What's Next
Considering for future versions based on community feedback:
- Fail2ban export format
- Path-based probe tracking (404 probes to /wp-admin, /.env, etc.)
- Sensor class architecture for better extensibility
Links
GitHub: https://github.com/jay123anta/laravel-threat-detection
Packagist: https://packagist.org/packages/jayanta/laravel-threat-detection
Feedback welcome.
Top comments (0)