jayanta / laravel-threat-detection
Real-time threat detection and security logging for Laravel applications. Detects SQL injection, XSS, DDoS, scanner bots, and more.
Requires
- php: ^8.1
- illuminate/cache: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/notifications: ^10.0|^11.0|^12.0
- illuminate/routing: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
Suggests
- laravel/sanctum: Recommended for API route authentication (^3.0|^4.0)
- laravel/slack-notification-channel: Required for Slack notifications on Laravel 11+ (^3.0)
README
Laravel Threat Detection
Know who's attacking your Laravel app — without changing a single line of code.
A zero-config, middleware-based Web Application Firewall (WAF) for Laravel. Drop it in, and it instantly starts detecting SQL injection, XSS, RCE, scanner bots, DDoS patterns, and 40+ other attack types — logging everything to your database with full geo-enrichment and a built-in dark-mode dashboard.
Extracted from a production application. Battle-tested with real traffic.
Why This Package?
| Problem | Solution |
|---|---|
| Laravel has no built-in request-level threat detection | This package scans every request through 100+ regex patterns |
| External WAF services cost money and add latency | Runs entirely within your app — zero external dependencies |
| Security logs are scattered across server files | Centralized database logging with API + dashboard |
| You don't know who's probing your app right now | Real-time Slack alerts + live threat count endpoint |
Dashboard Preview
The package ships with a built-in dark-mode dashboard (Alpine.js + Tailwind CDN — zero build step):
+-------------------------------------------------------------------------+
| Threat Detection Dashboard |
+-------------------------------------------------------------------------+
| Total: 847 | High: 23 | Med: 156 | Low: 668 | IPs: 94 |
+-------------------------------------------------------------------------+
| [████████ Timeline Chart - 7 Day Stacked Bar ████████] |
+-------------------------------------------------------------------------+
| Search: [___________] Level: [All ▼] |
| Time IP Type Level Confidence Actions |
| Mar 2 14:02 185.220.101.4 SQL Injection HIGH 80% [FP] |
| Mar 2 13:58 45.33.32.156 XSS Script Tag HIGH 65% [FP] |
| Mar 2 13:45 192.168.1.10 Scanner: Nikto MED 35% [FP] |
+-------------------------------------------------------------------------+
| Top IPs | Threats by Country |
| 185.220.101.4 [23] | US ████████████ 234 |
| 45.33.32.156 [18] | CN ████████ 156 |
| 103.152.220.1 [12] | RU ██████ 98 |
+-------------------------------------------------------------------------+
Enable with
THREAT_DETECTION_DASHBOARD=truein your.envNote: The dashboard fetches data from the API endpoints, which use
auth:sanctumby default. For the dashboard to work, your app must have Laravel Sanctum configured for SPA authentication (session-based). EnsureSANCTUM_STATEFUL_DOMAINSincludes your app domain, or change the API middleware in the config to['api', 'auth']if you use standard session auth.
Quick Start
# Install composer require jayanta/laravel-threat-detection # Publish & migrate php artisan vendor:publish --tag=threat-detection-config php artisan vendor:publish --tag=threat-detection-migrations php artisan migrate
Register the middleware:
Laravel 11+ (bootstrap/app.php):
->withMiddleware(function (Middleware $middleware) { $middleware->web(append: [ \JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class, ]); })
Laravel 10 (app/Http/Kernel.php):
protected $middlewareGroups = [ 'web' => [ // ... other middleware \JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class, ], ];
That's it. Your app is now detecting threats.
Features
- 40+ Attack Patterns — SQL injection, XSS, RCE, directory traversal, SSRF, XXE, Log4Shell, and more
- Scanner Detection — SQLMap, Nikto, Nmap, Burp Suite, Acunetix, WPScan, Dirbuster
- Bot Detection — Suspicious user agents, automated scripts, headless browsers
- DDoS Monitoring — Rate-based threshold detection with configurable windows
- Confidence Scoring — Each threat gets a 0-100 confidence score based on pattern count, context, and signals
- False Positive Reporting — Mark threats as false positives from the dashboard; auto-creates exclusion rules
- Tunable Sensitivity — Three detection modes:
strict,balanced(default), andrelaxed - Context-Aware Detection — Patterns found in query strings score higher than those in POST body
- Content Path Suppression — Whitelist CMS/blog paths to suppress low/medium alerts from rich content
- PII Detection — Sensitive data exposure patterns (configurable per region)
- Geo-Enrichment — Country, city, ISP, cloud provider identification via free API
- Slack Alerts — Real-time notifications for high-severity threats
- Built-in Dashboard — Dark-mode Blade dashboard (Alpine.js + Tailwind CDN)
- 15 API Endpoints — Full REST API for custom Vue/React/mobile dashboards
- CSV Export — One-click threat log export
- Correlation Analysis — Detect coordinated attacks and attack campaigns
- Database Agnostic — MySQL, PostgreSQL, SQLite, SQL Server
- Zero Config — Works out of the box with sensible defaults
Configuration
Add to your .env file:
# Core THREAT_DETECTION_ENABLED=true # Detection sensitivity: strict, balanced (default), relaxed THREAT_DETECTION_MODE=balanced # Whitelist IPs (comma-separated, supports CIDR) THREAT_DETECTION_WHITELISTED_IPS=127.0.0.1,10.0.0.0/8 # DDoS thresholds THREAT_DETECTION_DDOS_THRESHOLD=300 THREAT_DETECTION_DDOS_WINDOW=60 # Notifications THREAT_DETECTION_NOTIFICATIONS=false THREAT_DETECTION_SLACK_WEBHOOK=https://hooks.slack.com/services/... THREAT_DETECTION_SLACK_CHANNEL=#threat-alerts # API & Dashboard THREAT_DETECTION_API=true THREAT_DETECTION_DASHBOARD=true
Slack Notifications (Laravel 10.13+)
Laravel 10.13+ removed the built-in Slack notification channel. Install separately:
composer require laravel/slack-notification-channel
Environment Note
By default, detection runs in production, staging, and local. Change in your published config:
'enabled_environments' => ['production', 'staging', 'local'],
API Endpoints
The package provides 15 authenticated REST endpoints for building custom dashboards.
Security: API routes use
auth:sanctummiddleware by default. Updateapi.middlewarein your config to change.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/threat-detection/threats |
List threats (paginated, filterable) |
| GET | /api/threat-detection/threats/{id} |
Single threat details |
| POST | /api/threat-detection/threats/{id}/false-positive |
Mark threat as false positive |
| GET | /api/threat-detection/stats |
Overall statistics |
| GET | /api/threat-detection/summary |
Detailed breakdown by type, level, IP |
| GET | /api/threat-detection/live-count |
Threats in last hour |
| GET | /api/threat-detection/by-country |
Grouped by country |
| GET | /api/threat-detection/by-cloud-provider |
Grouped by cloud provider |
| GET | /api/threat-detection/top-ips |
Top offending IPs |
| GET | /api/threat-detection/timeline |
Threat timeline (for charts) |
| GET | /api/threat-detection/ip-stats?ip=x.x.x.x |
Stats for specific IP |
| GET | /api/threat-detection/correlation |
Correlation analysis |
| GET | /api/threat-detection/export |
Export to CSV |
| GET | /api/threat-detection/exclusion-rules |
List exclusion rules |
| DELETE | /api/threat-detection/exclusion-rules/{id} |
Delete an exclusion rule |
Query Parameters for /threats
| Parameter | Description |
|---|---|
keyword |
Search in IP, URL, type |
ip |
Filter by IP address |
level |
Filter by threat level (high, medium, low) |
type |
Filter by threat type |
country |
Filter by country code |
is_foreign |
Filter foreign IPs (true/false) |
cloud_provider |
Filter by cloud provider |
is_false_positive |
Filter by false positive status (true/false) |
date_from / date_to |
Date range |
per_page |
Items per page (default: 20, max: 100) |
Artisan Commands
# View threat stats in CLI php artisan threat-detection:stats # Enrich logs with geo-data php artisan threat-detection:enrich --days=7 # Purge old logs php artisan threat-detection:purge --days=30
Using the Facade
use JayAnta\ThreatDetection\Facades\ThreatDetection; // Get IP statistics $stats = ThreatDetection::getIpStatistics('192.168.1.1'); // Detect coordinated attacks $attacks = ThreatDetection::detectCoordinatedAttacks(15, 3); // Detect attack campaigns $campaigns = ThreatDetection::detectAttackCampaigns(24); // Get correlation summary $summary = ThreatDetection::getCorrelationSummary();
Custom Patterns
Add your own detection patterns in config/threat-detection.php:
'custom_patterns' => [ '/your-regex-pattern/i' => 'Your Threat Label', '/another-pattern/' => 'Another Threat', ],
Configure threat level mappings:
'threat_levels' => [ 'high' => ['XSS', 'SQL Injection', 'RCE', 'Token', 'Password'], 'medium' => ['Directory Traversal', 'LFI', 'SSRF', 'Config'], 'low' => ['User-Agent', 'Bot', 'Rate'], ],
Reducing False Positives
The package includes several features to minimize false positives without missing real threats.
Detection Modes
Set THREAT_DETECTION_MODE in your .env:
| Mode | Behavior |
|---|---|
strict |
All patterns active, lowest thresholds. Catches everything but may flag legitimate traffic. |
balanced |
Default. Confidence scoring active, standard thresholds. Good for most apps. |
relaxed |
Only high-severity patterns trigger. Best for content-heavy sites with frequent false positives. |
Content Path Suppression
If you have CMS editors, blog post forms, or comment sections where users submit rich content, add those paths to suppress low/medium alerts:
// config/threat-detection.php 'content_paths' => [ 'admin/posts/*', 'admin/pages/*', 'blog/*/edit', 'comments', ],
On these paths, only high-severity threats (real attacks) will be logged.
False Positive Reporting
Click the FP button on any threat in the dashboard to mark it as a false positive. This:
- Flags the threat as
is_false_positive = true - Auto-creates an exclusion rule so similar threats are suppressed going forward
Manage exclusion rules via API:
# List rules GET /api/threat-detection/exclusion-rules # Delete a rule DELETE /api/threat-detection/exclusion-rules/{id}
Confidence Scoring
Every threat receives a confidence score (0-100) based on:
- Number of pattern matches in the same request
- Severity of the matched pattern
- Where the pattern was found (query string > headers > body)
- Whether the user-agent matches a known attack tool
- Current detection mode
Threats below the confidence threshold are not logged:
strict: threshold 0 (log everything)balanced: threshold 10relaxed: threshold 40
Building Custom Frontends
Vue.js
async mounted() { const response = await fetch('/api/threat-detection/stats'); this.stats = await response.json(); const threats = await fetch('/api/threat-detection/threats?per_page=20'); this.threats = await threats.json(); }
React
useEffect(() => { fetch('/api/threat-detection/stats') .then(res => res.json()) .then(data => setStats(data)); }, []);
Detected Attack Types
| Category | Examples |
|---|---|
| Injection | SQL injection, NoSQL injection, command injection, LDAP injection |
| XSS | Script tags, event handlers, JavaScript URIs, DOM manipulation |
| Code Execution | RCE, PHP deserialization, template injection, eval() |
| File Access | Directory traversal, LFI/RFI, sensitive file probes (.env, wp-config) |
| SSRF | Localhost access, AWS/GCP metadata endpoints |
| Authentication | Brute force detection, token leaks, password exposure |
| Scanners | SQLMap, Nikto, Nmap, Burp Suite, Acunetix, WPScan |
| Bots | Automated scripts, suspicious user agents, headless browsers |
| DDoS | Rate-based excessive request detection |
| XXE | XML external entity attacks |
| Log4Shell | JNDI injection attempts |
Geo-Enrichment
Enrich threat logs with country, city, ISP, and cloud provider data:
php artisan threat-detection:enrich --days=7
Uses the free ip-api.com service (HTTP, rate-limited to 45 req/min — auto-throttled).
Testing
composer test
The package includes 61 tests covering service detection, middleware behavior, API endpoints, confidence scoring, exclusion rules, DDoS detection, and input validation.
Requirements
- PHP 8.1+
- Laravel 10.x, 11.x, or 12.x
License
MIT License. See LICENSE for details.
Contributing
Contributions are welcome! Please submit a Pull Request.