PHPackages                             dgtlss/warden - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [DevOps &amp; Deployment](/categories/devops)
4. /
5. dgtlss/warden

ActiveLibrary[DevOps &amp; Deployment](/categories/devops)

dgtlss/warden
=============

A deterministic Laravel security gate for CI and deployment pipelines

v2.0.0(1mo ago)9366.7k—8.8%10[2 issues](https://github.com/dgtlss/warden/issues)[3 PRs](https://github.com/dgtlss/warden/pulls)MITPHPPHP &gt;=8.3 &lt;8.6CI passing

Since Nov 18Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/dgtlss/warden)[ Packagist](https://packagist.org/packages/dgtlss/warden)[ RSS](/packages/dgtlss-warden/feed)WikiDiscussions main Synced 2w ago

READMEChangelog (10)Dependencies (37)Versions (34)Used By (0)

Warden
======

[](#warden)

A deterministic security gate for Laravel CI and deployment pipelines.

 [![Tests](https://github.com/dgtlss/warden/actions/workflows/tests.yml/badge.svg)](https://github.com/dgtlss/warden/actions) [![Latest Version on Packagist](https://camo.githubusercontent.com/2151e92019b7de5d050b9a0987ae81040e9aa24a3af920dc126c3b1a95c301b3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6467746c73732f77617264656e3f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dgtlss/warden) [![Total Downloads](https://camo.githubusercontent.com/d5e7512e30dabecd0fdd8e5011aca870614ccff612b72b865e67b628ef37b4f4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6467746c73732f77617264656e3f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dgtlss/warden) [![PHP Version](https://camo.githubusercontent.com/c0301b784ed65fb8ef7fa3a27f7355f9c587f34a7d61669b746fb31e33d02f3d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6467746c73732f77617264656e3f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dgtlss/warden) [![License](https://camo.githubusercontent.com/2250bc72c011ec1558a05447c4c839b4b0062e0087f2889e9c6cd128171c48c0/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6467746c73732f77617264656e3f7374796c653d666c61742d737175617265)](https://github.com/dgtlss/warden/blob/main/LICENSE)

Introduction
------------

[](#introduction)

Warden audits locked production dependencies, supply-chain configuration, and high-confidence Laravel production settings without becoming part of the deployed application.

Requirements
------------

[](#requirements)

- PHP 8.3–8.5
- Laravel 12 or 13
- Composer 2
- npm only when a `package-lock.json` is present

Installation
------------

[](#installation)

Install Warden as a development dependency:

```
composer require --dev dgtlss/warden
```

Laravel discovers Warden automatically. If package discovery is disabled, register `Dgtlss\Warden\Providers\WardenServiceProvider::class` in your application's providers array.

Usage
-----

[](#usage)

Run Warden **before** pruning development dependencies from the production artifact:

```
composer install --no-interaction
php artisan warden:audit --profile=production --scope=production
composer install --no-dev --no-interaction --optimize-autoloader
```

Initialize Warden safely and optionally generate a dedicated CI file:

```
php artisan warden:init --ci=github
# or: --ci=gitlab|both|none
```

`warden:init` never overwrites an existing `config/warden.php` or root GitLab pipeline. `--force` may replace only Warden-owned generated CI files. Publishing with `vendor:publish --tag=warden-config` remains available for manual setups.

### CI usage

[](#ci-usage)

The default command uses the CI profile, audits production dependencies, reports every finding, and fails on low severity or higher:

```
php artisan warden:audit
```

Common examples:

```
# Gate only on high and critical findings while still reporting everything
php artisan warden:audit --fail-on=high

# Validate effective production configuration
php artisan warden:audit --profile=production

# Audit production and development dependencies
php artisan warden:audit --scope=all

# Select or skip audits
php artisan warden:audit --only=supply-chain,composer,laravel-config,platform,source
php artisan warden:audit --skip=npm,storage

# Produce CI artifacts
php artisan warden:audit --format=json --output-file=warden-report.json
php artisan warden:audit --format=sarif --output-file=warden.sarif
php artisan warden:audit --format=gitlab --output-file=gl-dependency-scanning-report.json
php artisan warden:audit --format=junit --output-file=warden-junit.xml
```

Machine formats never mix progress or diagnostic prose into stdout. Scanner failures are included in the report and exit with code `2`.

### Exit codes

[](#exit-codes)

CodeMeaning`0`Every audit completed and no blocking finding met `--fail-on``1`One or more blocking findings met `--fail-on``2`Configuration, tool, timeout, malformed output, or audit execution failure### Profiles

[](#profiles)

ProfileBehavior`ci`Default. Static repository and dependency checks without assuming a runtime `.env` exists`production`Adds effective Laravel configuration and deployment filesystem checks`local`Static checks suitable for a developer workstationCI environment variables do not disable production checks. Use `--profile=production` when the pipeline has loaded the intended deployment configuration.

### Built-in audits

[](#built-in-audits)

- `supply-chain`: lockfile presence/synchronization, secure Composer repositories, plugin allow-listing, and JavaScript lockfile support
- `composer`: Composer advisories, malware, and abandoned production packages from `composer.lock`
- `npm`: npm advisories from `package-lock.json`, auto-detected without a flag
- `laravel-config`: tracked `.env` detection and production application/session/tooling rules
- `platform`: offline PHP and Laravel support-window enforcement, including Composer's exact platform target
- `source`: parser-backed PHP taint analysis, Blade review, and redacted credential detection
- `storage`: production-only operational warnings; these do not fail the security gate

Yarn, pnpm, and Bun lockfiles are detected but are not yet parsed. Warden reports the limitation so the package-manager-native audit can be added as a separate CI step.

### Source security model

[](#source-security-model)

Warden parses each selected PHP file once and distinguishes enforcement from review guidance:

- Blocking rules require a high-confidence condition such as request-controlled data reaching a command, raw output, outbound URL, redirect, deserializer, or filesystem sink. Other blocking rules cover interpolated raw SQL, disabled TLS verification, provider-format credentials, weak constant ciphers, and explicit CSRF middleware removal.
- Advisory rules highlight unescaped Blade output, forms without an obvious CSRF directive, mass-assignment disabling, debug calls, sensitive logging, weak contextual hashing/randomness, and secret-like literals.

Credentials are never copied into reports. Warden emits only the provider, location, and a redacted description; the secret contributes only a one-way hash to the stable fingerprint.

Default PHP scan paths are `app`, `bootstrap`, `config`, and `routes`; Blade templates are read from `resources/views`. File paths, exclusions, and the 1 MiB file limit are configurable under `warden.audits.source`. A selected file that cannot be read or parsed makes the scan incomplete and exits `2`.

### Rule policy

[](#rule-policy)

Every configurable rule has a stable ID and a built-in disposition. Override one without suppressing individual occurrences:

```
'rule_overrides' => [
    'source.blade.unescaped-output' => 'enforced',
    'source.php.debug-call' => 'off',
],
```

Allowed values are `enforced`, `advisory`, and `off`. Unknown rule IDs and invalid values are configuration errors. Advisory findings remain visible in every report but do not affect exit `1`; suppressions and baselines still apply to them.

See the complete [rule catalogue](docs/rules.md) for stable IDs, default dispositions, and rationale.

### Supply-chain review window

[](#supply-chain-review-window)

Composer packages released within three days produce an advisory. A recent package becomes a blocking critical finding when it is a Composer plugin or registers `autoload.files`, because it can execute automatically. The window is offline, uses `composer.lock` timestamps, respects `--scope`, and is configurable with `warden.audits.supply_chain.minimum_release_age_days`.

### Reviewed suppressions

[](#reviewed-suppressions)

Suppressions are exact, documented, and expiring. Wildcards are not supported.

```
'ignore_findings' => [
    [
        'id' => 'composer.advisory.ghsa-example',
        'fingerprint' => 'optional-fingerprint-for-one-occurrence',
        'reason' => 'Compensating control reviewed in SEC-123',
        'expires_at' => '2099-12-31',
    ],
],
```

An expired or malformed suppression is a configuration error and exits `2`.

### Baselines

[](#baselines)

Legacy applications can commit an explicit fingerprint baseline while continuing to fail on new findings:

```
php artisan warden:baseline \
  --reason="Existing findings tracked in SEC-123" \
  --expires=2099-12-31
```

This creates `warden-baseline.json`. Baseline generation refuses to write a file if any audit is incomplete.

### Reports

[](#reports)

Warden supports:

- `console`: readable terminal report
- `json`: versioned Warden schema with audits, blocking/advisory counts, findings, ignored findings, errors, and summary; the schema ships at `resources/schemas/warden-report-2.0.0.json`
- `github`: GitHub Actions workflow annotations
- `gitlab`: GitLab dependency scanning report schema 15.2.4
- `sarif`: SARIF 2.1.0 for GitHub code scanning and compatible platforms
- `junit`: portable JUnit XML for Jenkins and other CI systems

Advisory findings render as notices in GitHub and skipped tests in JUnit. SARIF and JSON preserve the `blocking` property.

`--output-file=-` writes to stdout. Relative file paths are resolved from the Laravel application root.

### Notifications

[](#notifications)

Notifications are opt-in and never affect the audit exit code:

```
php artisan warden:audit --notify
```

Configure any combination of:

```
WARDEN_SLACK_WEBHOOK_URL=
WARDEN_DISCORD_WEBHOOK_URL=
WARDEN_TEAMS_WEBHOOK_URL=
WARDEN_EMAIL_RECIPIENTS=security@example.com
WARDEN_EMAIL_FROM=warden@example.com
```

Each channel is dispatched once. Delivery failures are written to stderr after the report is produced.

### Custom audits

[](#custom-audits)

Custom audits receive the immutable audit context and return a typed result:

```
use Dgtlss\Warden\Contracts\CustomAudit;
use Dgtlss\Warden\Enums\Severity;
use Dgtlss\Warden\ValueObjects\AuditContext;
use Dgtlss\Warden\ValueObjects\AuditResult;
use Dgtlss\Warden\ValueObjects\Finding;

final class PublicBucketAudit implements CustomAudit
{
    public function getName(): string { return 'public-bucket'; }
    public function getDescription(): string { return 'Checks the effective filesystem configuration.'; }
    public function shouldRun(AuditContext $context): bool { return $context->profile === 'production'; }

    public function run(AuditContext $context): AuditResult
    {
        $findings = config('filesystems.disks.s3.visibility') === 'public'
            ? [new Finding(
                id: 'custom.storage.public',
                source: $this->getName(),
                title: 'S3 disk is public',
                severity: Severity::High,
                description: 'The default S3 disk visibility is public.',
                remediation: 'Set the disk visibility to private.',
                path: 'config/filesystems.php',
            )]
            : [];

        return AuditResult::complete($this->getName(), $findings);
    }
}
```

Register the class in `config/warden.php` under `custom_audits`.

Testing
-------

[](#testing)

```
composer install
composer test
composer phpstan
composer rector
composer validate --strict
```

Changelog
---------

[](#changelog)

Please see [the releases page](https://github.com/dgtlss/warden/releases) for a list of changes.

Contributing
------------

[](#contributing)

Please see [contributing.md](contributing.md) for contribution guidelines. Upgrading from Warden 1.x? Read [UPGRADE.md](UPGRADE.md) before changing the dependency constraint.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please report security vulnerabilities privately using [GitHub Security Advisories](https://github.com/dgtlss/warden/security/advisories/new).

License
-------

[](#license)

Warden is open-sourced software licensed under the [MIT license](LICENSE).

###  Health Score

60

—

FairBetter than 98% of packages

Maintenance92

Actively maintained with recent releases

Popularity46

Moderate usage in the ecosystem

Community17

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~28 days

Recently: every ~51 days

Total

22

Last Release

34d ago

Major Versions

1.3.2 → v2.0.x-dev2025-10-23

1.5.3 → v2.0.02026-07-14

PHP version history (3 changes)1.0.0PHP &gt;=8.1

1.4.0PHP &gt;=8.3

v2.0.0PHP &gt;=8.3 &lt;8.6

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/32520453?v=4)[Nathan Langer](/maintainers/dgtlss)[@dgtlss](https://github.com/dgtlss)

---

Top Contributors

[![dgtlss](https://avatars.githubusercontent.com/u/32520453?v=4)](https://github.com/dgtlss "dgtlss (53 commits)")[![nlangerdevtbg](https://avatars.githubusercontent.com/u/169651551?v=4)](https://github.com/nlangerdevtbg "nlangerdevtbg (32 commits)")[![cursoragent](https://avatars.githubusercontent.com/u/199161495?v=4)](https://github.com/cursoragent "cursoragent (21 commits)")[![MarkLanser](https://avatars.githubusercontent.com/u/16336154?v=4)](https://github.com/MarkLanser "MarkLanser (4 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (1 commits)")

---

Tags

cvelaravellaravel-frameworklaravel-packagelaravel-securitylaravel-security-checkerphpphp8securitysecurity-toolsvulnerabilitiesvulnerabilityvulnerability-scannerswardencomposerlaravelsecuritynotificationsciauditsvulnerabilitiescveSASTsupply-chainsecret-scanning

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Type Coverage Yes

### Embed Badge

![Health badge](/badges/dgtlss-warden/health.svg)

```
[![Health](https://phpackages.com/badges/dgtlss-warden/health.svg)](https://phpackages.com/packages/dgtlss-warden)
```

###  Alternatives

[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

265.2k](/packages/aedart-athenaeum)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9922.4M146](/packages/roots-acorn)[laravel/framework

The Laravel Framework.

34.9k556.2M21.5k](/packages/laravel-framework)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M322](/packages/laravel-ai)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

79227.1M228](/packages/laravel-mcp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
