Laravel gives you a lot out of the box — CSRF protection, encrypted cookies, mass assignment guards, and more. But in real-world SaaS development, misconfigurations creep in. Secrets leak. Authorization gets skipped. And standard linters don’t catch it.
That’s where Ward comes in — a purpose-built security scanner for Laravel that understands your app’s structure and runs deep, contextual checks. It’s not just a grep tool. It’s a full-blown security pipeline with a beautiful terminal UI and CI integration.
🧠 What Makes Ward Different?
Ward doesn’t just scan files. It resolves your Laravel project — routes, models, controllers, Blade templates, config files, environment variables, Composer dependencies — and then runs targeted security checks.
It catches what other tools miss:
APP_DEBUG=truein production- Controllers missing
authorize() $guarded = []on sensitive modelsDB::raw()with interpolated user input- Session cookies without
Secureflag - Blade templates using
{!! !!}on user data - Outdated Composer packages with known CVEs
- API routes missing
auth:sanctummiddleware
Ward is designed to fit into your workflow — run it locally during development or wire it into CI to gate deployments.
🔍 How Ward Works: 5-Stage Pipeline
Ward’s architecture is clean and modular:
- Provider — Locates and prepares your project (local path or git URL).
- Resolvers — Parses
.env,composer.json,config/*.phpto build a structured context. - Scanners — Runs independent security checks across environment, config, dependencies, and custom rules.
- Post-Process — Deduplicates findings, filters by severity, diffs against previous scans.
- Report — Generates output in JSON, SARIF, HTML, and Markdown formats.
This pipeline ensures deep, contextual analysis — not just surface-level pattern matching.
🛡️ Built-In Scanners
Ward ships with four powerful scanners:
| Scanner | What It Checks |
|---|---|
env-scanner | .env misconfigurations — debug mode, missing keys, leaked secrets |
config-scanner | config/*.php — insecure defaults, hardcoded credentials, missing flags |
dependency-scanner | composer.lock — live CVE lookup via OSV.dev against Packagist advisories |
rules-scanner | 42 YAML rules covering secrets, injection, XSS, debug artifacts, crypto, auth |
These scanners cover the most common — and most dangerous — Laravel security pitfalls.
🧪 Example: Detecting Dangerous Defaults
Let’s say your app has this in production:
// .env
APP_DEBUG=true
APP_KEY=
Ward flags both as critical issues:
ENV-002: Debug mode enabled in productionENV-003: Empty or missing APP_KEY
It also checks for:
- Weak default keys
- Real credentials in
.env.example - File-based sessions in production
- Unsecured cookies and CORS wildcards
These are the kinds of issues that slip through manual review — but Ward catches them instantly.
📦 Composer CVE Scanning
Ward reads your composer.lock as a software bill of materials (SBOM) and queries the OSV.dev vulnerability database in real time.
It covers:
- Laravel
- Symfony
- Guzzle
- Doctrine
- Monolog
- Livewire
- Filament
- Every other Packagist dependency
Results include CVE IDs, severity, affected versions, fixed versions, and remediation commands. This is live CVE scanning — not a hardcoded list.
🧰 Custom Rules with YAML
Want to scan for hardcoded internal URLs?
- id: TEAM-001
title: "Hardcoded internal service URL"
description: "Detects hardcoded URLs to internal services."
severity: medium
category: Configuration
enabled: true
patterns:
- type: regex
target: php-files
pattern: 'https?://internal-service\\.\\w+'
remediation: |
Use environment variables: $url = env('INTERNAL_SERVICE_URL');
Drop this into ~/.ward/rules/ and Ward picks it up automatically. No recompilation needed.
📈 Scan History & Diffing
Ward saves every scan to ~/.ward/store/. On subsequent scans, it shows:
[info] vs last scan: 2 new, 3 resolved (12→11)
This lets you track your security posture over time and catch regressions before they ship.
🖥️ Beautiful Terminal UI
Ward’s TUI (built with Bubble Tea) adapts to light and dark terminals. It shows:
- Live scan progress
- Severity counts
- Scrollable event log
- Sortable findings table
- Detail panel with code snippet, remediation, and references
It’s fast, intuitive, and developer-friendly.
⚙️ CI Integration
Ward fits into your CI pipeline with ease:
GitHub Actions:
- name: Run Ward
run: ward scan . --output json
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ward-report.sarif
GitLab CI:
ward-scan:
image: golang:latest
script:
- go install github.com/eljakani/ward@latest
- ward init && ward scan . --output json
artifacts:
paths:
- ward-report.*
when: always
You can gate deployments based on severity, track trends, and upload SARIF reports for GitHub Code Scanning.
🧠 Philosophy: Interface-First, Event-Driven
Ward’s architecture is built around:
- Interfaces — every component is a Go interface
- EventBus — scanners emit findings, TUI subscribes
- Shared Context — resolvers build once, scanners consume
- Rules as Data — YAML rules, no recompilation
This makes it extensible, testable, and future-proof.
🔮 Roadmap Highlights
- AI-assisted scanning
- Policy engine for CI pass/fail thresholds
- More resolvers: routes, models, controllers, middleware
- PHP AST-based scanning
- Per-project
.ward.yamlconfig
Ward is already powerful — but its roadmap shows it’s just getting started.
Final Thoughts
Ward isn’t just a scanner. It’s a security orchestration engine for Laravel.
It understands your app’s structure, runs deep contextual checks, and fits into your workflow — from local dev to CI pipelines.
If you’re building Laravel apps in 2026, Ward is the tool that helps you ship secure by default.
