Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Security Checker Laravel Package

jorijn/laravel-security-checker

Laravel Security Checker scans your Composer dependencies for known vulnerabilities using the FriendsOfPHP security advisories database. Run it via an Artisan command or schedule it, and get notified through email, Slack, Telegram, or Discord when security issues affect your app.

View on GitHub
Deep Wiki
Context7

Getting Started

jorijn/laravel-security-checker compares your composer.lock against the FriendsOfPHP security advisories database and reports known vulnerabilities, with optional notifications to mail, Slack, Discord, Telegram, Teams and ntfy.

composer require jorijn/laravel-security-checker
php artisan vendor:publish --tag=config   # publishes config/security-checker.php
php artisan security-checker:check

Look at these first, in order:

  1. config/security-checker.php — the only file you normally touch.
  2. Your .env — every config key has an LCS_* env counterpart; keep the truth there so it's per-environment.
  3. The README's notification section — copy the channel block you need verbatim rather than inventing keys.

The first use case worth wiring up is a scheduled daily run that posts to a team channel, because the command is only useful if someone actually sees the output. A second, equally common use case is a CI step: the command exits non-zero when vulnerabilities are found, so a plain step in the pipeline is enough to fail the build.

Implementation Patterns

Scheduled monitoring (the default pattern). Register the command in routes/console.php or the scheduler and let notifications do the delivery:

Schedule::command('security-checker:check')
    ->dailyAt('07:00')
    ->withoutOverlapping();

Notifications are configured entirely in config/security-checker.php; enable one channel per environment and keep the webhook URLs / recipients in .env. Don't fan out to every channel — a weekly digest in one place beats a daily message nobody reads.

CI gate. Run php artisan security-checker:check as a pipeline step early (before the slow test suite) so a vulnerable dependency fails fast. In a production build pipeline where composer install --no-dev is used, add LCS_EXCLUDE_DEV=true so dev-only packages don't block a release. Keep a separate, non-exclude_dev run for the branch that developers actually build against.

The allow_list triage loop. When an advisory is reported that you have decided not to act on, add it to LCS_ALLOW_LIST by CVE identifier rather than by title:

LCS_ALLOW_LIST='["CVE-2024-1234"]'

Prefer CVEs — advisory titles get reworded and then your suppression silently stops matching (or worse, matches the wrong advisory). Pair each entry with a ticket reference in your own notes, and review the list on a schedule; it has no expiry mechanism of its own.

exclude_dev as a signal, not a silencer. Dev dependencies are still recorded in composer.lock even when --no-dev is used at install time, so the checker reports them by default. Set LCS_EXCLUDE_DEV=true only where those packages genuinely never run — production images and release jobs. Leave it off in the environment developers use.

Webhook / on-demand runs. For setups where CI cannot shell into the app (or where you want a single shared check server), the package supports running as a listener that other systems can trigger. That's the right choice for multi-repo organisations; for a single Laravel app, the scheduled command is simpler and easier to debug.

Gotchas and Tips

  • The .env quoting rule is not optional. LCS_ALLOW_LIST must be a single-quoted JSON array: LCS_ALLOW_LIST='["CVE-2024-1234","Some title"]'. Double-quoted values get mangled by dotenv's own parsing, and you'll spend an hour wondering why nothing is being suppressed.
  • An invalid allow list fails open, not closed. Per the release notes, malformed JSON is logged as a warning and ignored, so the check still runs. That's the safe default for security — but it means a typo doesn't break your pipeline, it just quietly resurrects vulnerabilities you thought were suppressed. After editing, verify the parsed value (php artisan tinker → config('security-checker.allow_list')) instead of trusting the run to be quiet.
  • php artisan config:cache will bite you. Any change to .env needs php artisan config:clear (or a re-cache) before the scheduled run sees it — especially in deployments where config is cached at build time.
  • Title-based allow-list entries are brittle. Exact advisory titles are matched literally; upstream renames an advisory and the entry becomes dead weight. Only fall back to titles for advisories that have no CVE assigned, and re-audit those entries after every dependency upgrade.
  • A clean run is not proof of a clean app. The checker only knows about advisories in the public database for packages in composer.lock — abandoned packages with no advisories, unmaintained transitive dependencies and application-level code are invisible to it. Don't let a green scheduled job substitute for composer outdated and periodic dependency review.
  • Caching and just-disclosed CVEs. Results are cached, so a CVE published an hour ago may not appear on the next run. If you're validating a fix, force a fresh run rather than trusting the first clean output.
  • Exit codes matter more than output in CI. Don't || true the step to keep the pipeline green — use allow_list for accepted risk so that the reason a vulnerability is tolerated is recorded in version control rather than in a CI config.
  • Upgrade notes for this release. exclude_dev and allow_list are additive and default to off/empty, so v3.0.0 config files keep working untouched. If you publish a new config file, diff it against yours rather than overwriting — the notification blocks are easy to lose.
  • Extension point: notification channels are config-driven. Adding an internal channel (e.g. a PagerDuty or MS Teams variant) means extending the notifier layer, but for most teams it's cheaper to route the existing Slack/Discord webhook through your alerting tool than to write code.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route