dgtlss/warden
Warden is a Laravel package that runs security audits against your application, flagging common misconfigurations, exposed files, and risky settings. It provides actionable Artisan reports and configurable checks so teams can catch issues early and keep production environments protected.
artisan command, framework-aware analysis, CI bootstrapping) rather than on breadth, so the decision is really "adopt a Laravel-native gate alongside, not instead of, a platform SAST/SCA tool."--report=json-v2.1:… --report=sarif:… --report=junit:…) sharing a single timestamp, suppression set, and gate outcome. That is a direct lever on CI minutes and on the number of pipeline steps a platform team has to maintain: one job can simultaneously feed GitHub code scanning, a JUnit test dashboard, and a retained compliance artifact. If your pipeline currently runs the scanner two or three times to get different formats, this release removes that duplication.--fail-on drives JUnit failures and GitHub annotations consistently across all reports, which means "what blocks a merge" is now a single, auditable knob rather than per-format behavior. Choose the severity threshold deliberately and document it as policy; the package now makes the gate visible in the extended report schemas, which is what auditors and platform reviews tend to ask for.2 before any scanning. This turns suppressions into a time-boxed, auditable exception register instead of free-text that can silently rot. It supports a real process decision: require expiry dates on every waiver, and treat a malformed suppression file as a build break rather than a warning.json-v2.1 output, and counts explicitly documented as lower bounds. This is the deciding input for a risk-acceptance decision: a clean-but-incomplete scan is materially different from a clean complete scan, and the tooling now refuses to conflate them. Pair it with a policy that incomplete scans never count as evidence of compliance.warden.notifications.on_errors=true is set. That is a product decision your team has to make explicitly: opt in if you want noise about coverage gaps, leave it off if you only want to be paged on findings.2.0.0 schema and new JsonReporter() remains compatible; json-v2.1 (with gate and coverage fields) is opt-in via --format=json-v2.1, --report=json-v2.1:path, or new JsonReporter(extended: true). Generated CI opts in for you. This is a low-risk contract story to communicate to any team consuming Warden output downstream.Consider adopting when:
composer.json as a dev dependency, with no data egress and no seat-based pricing negotiation.npm-shrinkwrap.json correctly taking precedence over package-lock.json, and report output identifying which lockfile was selected)..env.example and .github files are now in scope, every credential match on a line is examined, and .env itself stays excluded. Equivalent paths like ./app and app/. resolve identically, so CI invocations are predictable.Look elsewhere when:
One operational caveat worth flagging before you commit: the release notes state that Composer derives the package version from Git tags and that merging, tagging, and publication are separate steps. Verify the tag is actually published before pinning ^2.2 in CI, and read UPGRADE.md for the intentional validation and notification changes.
For executives (one paragraph). Warden 2.2 is a low-cost, low-risk upgrade to a security check we run in CI: one scan now produces every report format our pipeline and auditors need, detection gets meaningfully better at catching real leaks, and the gate stays a single configurable threshold. Nothing downstream breaks — the default report format is unchanged and new fields are opt-in. The cost is a triage pass for findings the stricter analysis will newly surface; the benefit is a defensible, repeatable "we scan every change and we can prove what we found" story.
For engineering leads. The upgrade is additive. Default JSON, including public object serialization and new JsonReporter(), stays compatible with the unchanged strict 2.0.0 schema; the new gate and coverage fields live under a separate opt-in 2.1.0 schema, and the generated CI already opts in. Existing fingerprints and baselines keep matching unchanged source, so nobody re-baselines. The practical change is one scan producing multiple reports, which lets us delete redundant pipeline steps. Expect new findings — sink-scoped sanitizers, alias/Request/named-argument resolution, hidden-file credential coverage, and per-line credential matching are all false-negative reductions, not behavior regressions. Treat those as the point of the upgrade, not as breakage.
For security and compliance reviewers. Three properties matter here. First, integrity is now fail-fast: malformed suppression fingerprints or impossible expiry dates exit 2 before scanning, so an exception register cannot silently degrade. Second, coverage is honest: unreadable directories produce an explicitly incomplete scan with scanned/skipped/error counts documented as lower bounds, and incomplete reports describe the error rather than claiming all-clear. Third, notifications cannot corrupt results — delivery requires a configured flag and channel, never changes the audit exit code, and incomplete-scan alerting is an explicit opt-in (warden.notifications.on_errors=true). Teams payloads are capped at 28,000 encoded bytes with a pointer to the full report, so alerting degrades predictably. The right policy to pair with this: no suppression without an expiry, and no clean-build claim from an incomplete scan.
The ask. Approve a one-repo pilot at --fail-on=high with SARIF upload enabled, measure the newly surfaced findings over two weeks, then decide on org-wide rollout and triage capacity with real numbers instead of estimates. Success looks like: pilot repo green on a complete scan, a suppression file with dated expiries, and a triage budget the team has actually agreed to.
How can I help you explore Laravel packages today?