Security Standards

What Is CVE (Common Vulnerabilities and Exposures)?

A standardized identifier for publicly known security vulnerabilities. Each CVE entry includes a unique ID (e.g., CVE-2024-1234), a description, and severity rating. The CVE system is maintained by MITRE and used globally to track and reference vulnerabilities.

How It Works

The CVE system converts vulnerability discoveries into standardized, trackable records that security tools can act on automatically.

Step 1: Discovery and report — A security researcher finds a vulnerability in a software component — for example, a path traversal flaw in league/flysystem or an authentication bypass in laravel/framework. The researcher reports it to the package maintainer through a responsible disclosure process (often via GitHub Security Advisories), giving the maintainer time to develop a fix before public disclosure.

Step 2: Patch development — The maintainer develops a fix and prepares a new release. For Composer packages, this results in a new version tagged on Packagist (e.g., 2.4.1 patching the vulnerability in 2.4.0).

Step 3: CVE assignment — MITRE assigns a CVE identifier (e.g., CVE-2024-12345) to the vulnerability. The CVE record includes: a description of the vulnerability, the affected software versions, the patched version, and a CVSS severity score (0-10, with Critical ≥ 9.0).

Step 4: Database publication — The CVE is published to the National Vulnerability Database (NVD) and, for PHP packages, to the PHP Security Advisories database (github.com/FriendsOfPHP/security-advisories). Both databases are queryable by automated tools.

Step 5: Scanner detectioncomposer audit reads your composer.lock, extracts every installed package name and exact version, and queries the PHP Security Advisories API. If any installed version falls within a CVE's affected range, the advisory is reported with severity and the patched version number. This entire process runs in under one second.

Step 6: Exploitation window — Between CVE publication and patch deployment, your application is vulnerable to anyone who checks the CVE database. Automated exploitation tools often begin scanning for vulnerable versions within hours of a high-severity CVE being made public. Running composer update and redeploying immediately after a critical CVE is disclosed closes this window.

Types of CVE (Common Vulnerabilities and Exposures)

Direct Dependency CVE

A CVE affects a package listed directly in your `composer.json` `require` section — these are easy to see with `composer audit` and `composer outdated`.

# Check for CVEs in your direct dependencies
composer audit
# Output: guzzlehttp/guzzle 7.4.0 CVE-2022-29248 (High)

Transitive Dependency CVE

A CVE affects a package that one of your direct dependencies relies on — not listed in your `composer.json` but present in `composer.lock`. Equally dangerous, less visible.

# composer.lock shows transitive deps — audit checks all of them
composer show --tree | grep symfony/http-foundation

Core Framework CVE

A CVE is assigned to `laravel/framework` itself, requiring an update to a patched minor or patch version of Laravel.

# Update Laravel framework to patched version
composer update laravel/framework
composer audit  # Verify no remaining advisories

Runtime CVE

A CVE affects the PHP runtime engine or web server (Nginx, Apache) rather than any Composer package — requires OS-level patching outside the Composer ecosystem.

# Check PHP version CVEs
php -v  # Check current version
# Update PHP via package manager: apt upgrade php8.3

In Laravel Applications

Laravel and its dependencies receive CVE assignments when vulnerabilities are discovered. Run `composer audit` to check your project against the CVE database. Packages like symfony/http-foundation and guzzlehttp/guzzle frequently have CVEs that affect Laravel applications.

Code Examples

GitHub Actions CI Without vs. With composer audit

Vulnerable

# .github/workflows/ci.yml — MISSING security audit
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: composer install --no-dev
      - run: php artisan test
      # No composer audit — CVEs in dependencies are never caught

Secure

# .github/workflows/ci.yml — WITH security audit
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: composer install --no-dev
      - run: composer audit        # Fails build if CVEs found
      - run: php artisan test
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: composer audit --format=json > audit.json
      - uses: actions/upload-artifact@v4
        with:
          name: security-audit
          path: audit.json

Real-World Example

CVE-2021-43617 affected Laravel's password reset functionality. Teams using `composer audit` could detect and patch this before exploitation.

Why It Matters

CVEs are the shared language of the security community. When a vulnerability is assigned a CVE, it gets a severity score (CVSS), a description, and is added to public databases that vulnerability scanners check against. Understanding CVEs helps Laravel developers prioritize patching work based on actual risk.

The PHP and Laravel ecosystem generates CVEs regularly. Packages like symfony/http-foundation, guzzlehttp/guzzle, league/flysystem, laravel/framework itself, and the underlying PHP engine all have CVE histories. The composer audit command (available since Composer 2.4) checks your entire dependency tree against the PHP Security Advisories database and should run in every CI/CD pipeline.

CVSS scores range from 0 to 10, with 9.0+ being Critical. A Critical CVE in a package used by 80% of Laravel applications is qualitatively different from a Medium CVE in a rarely-used package. However, even Medium-severity CVEs should be patched promptly — attackers do not respect severity classifications.

The composer.lock file is the source of truth for what your application actually runs. A CVE in a transitive dependency (a dependency of a dependency) is just as dangerous as one in a direct dependency. Running composer audit against your composer.lock catches both.

Common Misconceptions

Myth: If the CVE affects a package version we do not use directly, we are safe.

Reality: CVEs in transitive dependencies (dependencies of your dependencies) are equally dangerous. `composer audit` checks the entire dependency tree in `composer.lock`, not just `require` in `composer.json`.

Myth: Low and Medium CVSS score CVEs can wait for the next release cycle.

Reality: CVSS scores reflect generic impact. A Medium CVE in your specific application context (e.g., one that enables email enumeration on your login endpoint) may be high-priority for your use case.

Myth: We do not need `composer audit` if we keep packages updated.

Reality: `composer update` installs newer versions but does not verify whether known vulnerabilities affect your installed versions. `composer audit` specifically cross-references against security advisory databases.

How to Detect This

Run `composer audit` from your project root to check all installed packages in `composer.lock` against the PHP Security Advisories database — this runs in under a second and should be part of every deployment pipeline. Integrate it into GitHub Actions with `- run: composer audit` in your CI workflow. StackShield monitors your production application for behavioral signs of CVE exploitation and alerts when new CVEs are disclosed that affect common Laravel dependencies. For a more comprehensive check, Snyk and the GitHub Security Advisories section of any package repository provide CVE scanning with additional context. Review the GitHub Dependabot alerts tab on your repository to see CVEs flagged automatically against your `composer.lock`.

How to Prevent This in Laravel

  1. 1

    Add `composer audit` as a required step in your GitHub Actions CI workflow — place it before tests so a CVE fails the build immediately and is never deployed.

  2. 2

    Enable Dependabot security alerts on your GitHub repository in Settings → Security → Code security and analysis to receive automatic PRs when CVEs affect your `composer.lock`.

  3. 3

    Run `composer outdated --direct` monthly to review packages with available updates and prioritize those with security-relevant changelogs.

  4. 4

    Subscribe to the PHP Security Advisories RSS feed at `github.com/FriendsOfPHP/security-advisories` and the Laravel security announcements mailing list to learn about CVEs before automated scanners report them.

  5. 5

    After `composer update` to patch a CVE, run `php artisan config:clear && php artisan route:clear && php artisan view:clear` to ensure cached configurations reflect the updated dependency.

Frequently Asked Questions

How do I check if my Laravel app has CVEs in its dependencies?

Run `composer audit` from your project root. It reads `composer.lock` and queries the PHP Security Advisories database, returning any CVEs affecting your installed packages in under a second. For a broader view, GitHub's Dependabot also scans `composer.lock` and opens pull requests automatically when CVEs are found. Both check the full dependency tree — including transitive dependencies not listed in `composer.json`.

What is the difference between `composer audit` and `composer outdated`?

`composer audit` specifically checks installed package versions against the PHP Security Advisories database for known CVEs — it does not report packages that simply have newer versions available. `composer outdated` shows packages where newer versions exist, regardless of security status. For security purposes, use `composer audit` in CI and `composer outdated --direct` periodically to review packages that may benefit from non-CVE bugfix and feature updates.

Does updating Laravel core fix all CVEs affecting my application?

No. `laravel/framework` updates fix CVEs in Laravel itself, but your `composer.lock` contains many other packages — Symfony components, Guzzle, League packages, and your own direct dependencies — each with their own CVE histories. Run `composer update` followed by `composer audit` to update all packages and verify no advisories remain. Updating only `laravel/framework` leaves potential CVEs in other packages unaddressed.

How quickly should I patch a Critical (CVSS ≥ 9.0) CVE?

Critical CVEs should be patched within 24 hours of disclosure. Automated exploitation tools begin scanning for vulnerable versions within hours of a high-profile CVE being published. Run `composer update package/name` to patch the specific package, run your test suite to verify no breaking changes, and deploy immediately. For CVEs with active exploitation in the wild (marked "KEV" in the CISA database), treat the patch as an emergency release regardless of your normal deployment schedule.

Related Terms

Monitor Your Laravel Application's Security

StackShield continuously checks your Laravel application from the outside, catching security issues before attackers find them.

Start Free Trial