paulohps/laravel-csw

A Laravel package to monitor Composer dependencies for security vulnerabilities

Maintainers

Package info

github.com/paulohps/laravel-csw

pkg:composer/paulohps/laravel-csw

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.0.7 2026-04-24 03:01 UTC

This package is auto-updated.

Last update: 2026-04-24 03:14:54 UTC


README

Tests PHP Version Laravel Version License

Automate composer audit in your Laravel application and receive vulnerability alerts via Log, Slack, Discord, Email, or Database — on a schedule or on demand.

Requirements

Dependency Version
PHP ^8.3
Laravel ^11.0 | ^12.0 | ^13.0
Composer ^2.4 (for audit command support)

Installation

Install the package via Composer:

composer require paulohps/laravel-csw

Publish the configuration file:

php artisan vendor:publish --tag="composer-security-watch-config"

Configuration

The published config file is located at config/composer-security-watch.php.

return [
    'enabled' => env('CSW_ENABLED', true),

    'schedule' => [
        'frequency' => env('CSW_SCHEDULE_FREQUENCY', '0 9 * * *'),
    ],

    'notify' => [

        // Job responsible for dispatching notifications.
        // Override 'class' for custom dispatch logic; set 'queue' to target a specific queue.
        'job' => [
            'class' => \LaravelCsw\Jobs\SendVulnerabilityNotificationsJob::class,
            'queue' => env('CSW_JOB_QUEUE', 'default'),
        ],

        'channels' => [
            'log' => [
                'enabled' => env('CSW_NOTIFY_LOG', true),
                'class'   => \LaravelCsw\Channels\LogChannel::class,
            ],
            'slack' => [
                'enabled'     => env('CSW_NOTIFY_SLACK', false),
                'class'       => \LaravelCsw\Channels\SlackChannel::class,
                'webhook_url' => env('CSW_SLACK_WEBHOOK_URL'),
            ],
            'discord' => [
                'enabled'     => env('CSW_NOTIFY_DISCORD', false),
                'class'       => \LaravelCsw\Channels\DiscordChannel::class,
                'webhook_url' => env('CSW_DISCORD_WEBHOOK_URL'),
            ],
            'email' => [
                'enabled'  => env('CSW_NOTIFY_EMAIL', false),
                'class'    => \LaravelCsw\Channels\EmailChannel::class,
                'to'       => env('CSW_EMAIL_TO'),
                'mailable' => \LaravelCsw\Mail\VulnerabilityReport::class,
            ],
            'database' => [
                'enabled' => env('CSW_NOTIFY_DATABASE', false),
                'class'   => \LaravelCsw\Channels\DatabaseChannel::class,
            ],
        ],
    ],
];

Available environment variables

Variable Description
CSW_ENABLED Enable/disable the package (true)
CSW_SCHEDULE_FREQUENCY Cron expression for scheduled audit (0 9 * * *)
CSW_NOTIFY_LOG Enable log channel (true)
CSW_NOTIFY_SLACK Enable Slack channel (false)
CSW_SLACK_WEBHOOK_URL Slack incoming webhook URL
CSW_NOTIFY_DISCORD Enable Discord channel (false)
CSW_DISCORD_WEBHOOK_URL Discord webhook URL
CSW_NOTIFY_EMAIL Enable email channel (false)
CSW_EMAIL_TO Recipient email address(es)
CSW_NOTIFY_DATABASE Enable database channel (false)
CSW_JOB_QUEUE Queue name for the notification job (default)

Usage

Artisan Command

Basic audit:

php artisan csw:audit

Returns exit code 0 when clean, 1 when vulnerabilities are found — useful in CI pipelines.

Audit + send notifications:

php artisan csw:audit --notify

Dispatches SendVulnerabilityNotificationsJob which sends alerts to all enabled channels.

Audit + update vulnerable packages:

php artisan csw:audit --update

Runs composer update vendor/package for each affected package.

Audit + update including all dependents:

php artisan csw:audit --update --with-all

Passes --with-all-dependencies to composer update. Requires --update.

Scheduled Audit

When enabled is true, CSW automatically registers a scheduled command at the configured cron frequency. Make sure your Laravel scheduler is running:

# Add to crontab
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1

The scheduled command runs: php artisan csw:audit --notify

Notification Channels

Log (default: enabled)

Writes a warning log entry for each vulnerability. Uses your application's default log channel.

Slack

Set up a Slack Incoming Webhook and add the URL to your config or .env:

CSW_NOTIFY_SLACK=true
CSW_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz

Discord

Create a webhook via Server Settings > Integrations > Webhooks:

CSW_NOTIFY_DISCORD=true
CSW_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxx/yyy

Email

Supports single address or an array of addresses:

CSW_NOTIFY_EMAIL=true
CSW_EMAIL_TO=security@example.com

For multiple recipients, set in config/composer-security-watch.php:

'email' => [
    'enabled' => true,
    'to'      => ['admin@example.com', 'security@example.com'],
],

To customise the email subject, headers, or template, override the mailable key with your own Mailable class. Its constructor must accept array $vulnerabilities as the first argument:

'email' => [
    'enabled'  => true,
    'to'       => env('CSW_EMAIL_TO'),
    'mailable' => \App\Mail\MyVulnerabilityReport::class,
],

Database

The database channel requires a migration. Install it with:

php artisan csw:install-database-channel
php artisan migrate

Then enable it:

CSW_NOTIFY_DATABASE=true

Vulnerabilities are stored in the composer_security_vulnerabilities table, accessible via the VulnerabilityRecord model:

use LaravelCsw\Models\VulnerabilityRecord;

VulnerabilityRecord::latest('found_at')->get();

Custom Notification Channels

Implement LaravelCsw\Contracts\NotificationChannel to create your own channel:

use LaravelCsw\Contracts\NotificationChannel;
use LaravelCsw\Data\Vulnerability;

class PagerDutyChannel implements NotificationChannel
{
    public function send(array $vulnerabilities): void
    {
        foreach ($vulnerabilities as $vulnerability) {
            // Send to PagerDuty...
        }
    }
}

Register it in the notify.channels config array — the class key is what the notification job uses to resolve the channel:

'notify' => [
    'channels' => [
        // ... existing channels ...
        'pager_duty' => [
            'enabled' => true,
            'class'   => \App\Channels\PagerDutyChannel::class,
        ],
    ],
],

You can also override a built-in channel by binding your own implementation in a service provider:

// In AppServiceProvider::register()
$this->app->bind(
    \LaravelCsw\Channels\SlackChannel::class,
    \App\Channels\CustomSlackChannel::class,
);

The Vulnerability Object

Notification channels receive an array of LaravelCsw\Data\Vulnerability objects:

readonly class Vulnerability
{
    public string $packageName;
    public string $version;
    public string $advisoryId;
    public string $title;
    public ?string $link;
    public ?string $cve;
}

Docker (local development)

A Docker environment is provided for running PHP and Composer without a local installation:

# Build the image
docker compose build

# Install dependencies
docker compose run --rm app composer install

# Run tests
docker compose run --rm app vendor/bin/pest

# Run audit
docker compose run --rm app php artisan csw:audit

Testing

# Run all tests
composer test

# Run tests with coverage report (requires 100%)
composer test-coverage

# Apply code style
composer format

Changelog

Please see CHANGELOG.md for recent changes.

Contributing

Please see CONTRIBUTING.md for details.

License

The MIT License (MIT). Please see License File for more information.