I Built a Free WAF for Laravel — Here's How It Works

Published: (March 3, 2026 at 09:22 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Last year, I noticed something unsettling in my Laravel app’s logs — hundreds of SQL injection attempts, scanner bots probing for /wp-admin, and XSS payloads stuffed into search fields. Every day.

I built a security module to detect and log these threats. After months of running it in production, I extracted it into a standalone Laravel package and open‑sourced it.

What It Does

laravel-threat-detection is a middleware that sits in front of your routes and inspects every incoming request against 100+ regex patterns. When it finds something suspicious, it logs it to your database with full context — IP, URL, payload, threat type, severity level.

  • No external services.
  • No API keys.
  • No build tools.
composer require jayanta/laravel-threat-detection

Register the middleware and you’re done.

What It Detects

  • SQL Injection — UNION attacks, stacked queries, blind SQLi
  • XSS — “ tags, event handlers, JavaScript URIs
  • Remote Code Executionsystem(), exec(), eval(), shell_exec()
  • Directory Traversal../../etc/passwd, LFI/RFI
  • Scanner Bots — SQLMap, Nikto, Nmap, Burp Suite, Acunetix, WPScan
  • DDoS — Rate‑based threshold detection
  • SSRF — Localhost access, AWS/GCP metadata endpoint probing
  • XXE, Log4Shell, LDAP injection — and 30+ more categories

The Dashboard

The package ships with a built‑in dark‑mode dashboard — no build step required. It uses Alpine.js + Tailwind CDN and fetches all data from the package’s JSON API.

Features:

  • Stats cards (total, high/medium/low severity, unique IPs)
  • 7‑day timeline chart
  • Searchable, filterable threat table with pagination
  • Top offending IPs
  • Threats by country

Enable it with one env variable:

THREAT_DETECTION_DASHBOARD=true

The API

If you prefer to build your own frontend, there are 12 REST endpoints, e.g.:

  • GET /api/threat-detection/stats — overall statistics
  • GET /api/threat-detection/threats — paginated, filterable threat list
  • GET /api/threat-detection/top-ips — top offending IPs
  • GET /api/threat-detection/by-country — grouped by country
  • GET /api/threat-detection/timeline — chart data
  • GET /api/threat-detection/export — CSV export

All endpoints return JSON. Build with Vue, React, Livewire — whatever you want.

Geo‑Enrichment

Run one Artisan command to enrich your threat logs with country, city, ISP, and cloud‑provider data:

php artisan threat-detection:enrich --days=7

Uses the free ip-api.com service, auto‑throttled to stay within rate limits.

Slack Alerts

Get real‑time Slack notifications for high‑severity threats:

THREAT_DETECTION_NOTIFICATIONS=true
THREAT_DETECTION_SLACK_WEBHOOK=https://hooks.slack.com/services/...

Quick Start

Install

composer require jayanta/laravel-threat-detection

Publish config & migrations

php artisan vendor:publish --tag=threat-detection-config
php artisan vendor:publish --tag=threat-detection-migrations
php artisan migrate

Register the middleware (Laravel 11+)

->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [
        \JayAnta\ThreatDetection\Http\Middleware\ThreatDetectionMiddleware::class,
    ]);
})

That’s it. Your app is now detecting threats.

Why I Built This

Most WAF solutions are either expensive cloud services or complex self‑hosted setups. I wanted something that:

  • Lives inside the Laravel app itself
  • Takes 2 minutes to set up
  • Costs nothing
  • Gives me visibility into who’s attacking my app

This package does exactly that.

  • GitHub:
  • Packagist:

Works with Laravel 10, 11, and 12. PHP 8.1+. MIT licensed.

Feedback, stars, and contributions are all welcome!

0 views
Back to Blog

Related posts

Read more »

Google Gemini Writing Challenge

What I Built - Where Gemini fit in - Used Gemini’s multimodal capabilities to let users upload screenshots of notes, diagrams, or code snippets. - Gemini gener...