Research · scanned 11 November 2026

The state of Laravel dependencies, November 2026

We pulled composer.lock from 839 public Laravel apps on GitHub and checked every locked version against the GitHub Advisory Database. Three weeks after Laravel fixed a critical authentication bypass, most of them still haven't updated.

69%

still run a laravel/framework version affected by the critical TokenGuard authentication bypass (GHSA-f9x3-7vq9-cph6), three weeks after the fix shipped.

79%

lock at least one package with a known advisory. The median app has 10, out of about 87 packages.

28%

are on Laravel 11 or older, which no longer get security fixes at all.

21%

were clean: no known advisory in any runtime package.

Is your project affected?

Private repo? Upload its lockfile instead, or connect GitHub to check every repo.

The TokenGuard bypass most apps haven't patched

GHSA-f9x3-7vq9-cph6 was published on 21 October 2026. When an app uses Laravel's built-in token guard on MySQL or MariaDB, a crafted non-string credential can authenticate as another existing user. It's rated critical. If you don't use the token guard you aren't exposed, but most teams can't answer that for every app without looking.

576 of the 839 apps (69%) lock an affected version. Of the 312 that link to their own website, so are probably deployed, 180 (58%) are affected. It's fixed in:

  • 13.x: 13.27.0
  • 12.x: 12.68.0
  • 11.x: 11.56.1
  • 10.x and older: 10.50.4

Which Laravel versions apps run

Laravel 12 and 13 still get security fixes. 238 apps (28%) are on a version that doesn't, so a framework advisory there has no patch on their release line.

The packages behind most findings

Most of these come in through Laravel itself, not composer.json, so nobody chose the version. The fix is usually a composer update of that package within its current constraint.

PackageApps on a vulnerable version
symfony/http-foundation619 (74%)
league/commonmark607 (72%)
laravel/framework594 (71%)
league/flysystem570 (68%)
guzzlehttp/guzzle505 (60%)
guzzlehttp/psr7444 (53%)
symfony/routing433 (52%)
symfony/mime406 (48%)

Why this happens, and the cheap fix

It isn't negligence. composer.lock gets committed once, the app works, and nobody opens it again until something breaks. composer audit would catch all of this, but someone has to remember to run it, in every repo, every week.

For one app, add composer audit to CI and fail the build on critical findings. If you look after several apps, especially client sites, NPMscan checks every repo each week and emails you when something new turns up. Indie is $5 a month for 15 repos, and the first 3 are free.

How we did it

We searched GitHub for Laravel and Statamic application repos (topics such as laravel-application, crm, saas, cms, ecommerce, dashboard and statamic) pushed since November 2025, and kept the 839 with a composer.lock on the default branch that requires laravel/framework or statamic/cms. Packages and libraries are mostly excluded because they don't commit a lockfile.

Every locked version in the lockfile's runtime packages (dev dependencies excluded) was checked against the OSV Packagist feed, which includes the GitHub Advisory Database and FriendsOfPHP. Withdrawn advisories are ignored, and an advisory listed under several IDs is counted once.

Caveats: public repos include demos, coursework and starter kits, so read this as "public Laravel code", not "Laravel in production". The 312 apps that link to their own website are the closest we have to deployed apps, and they show the same pattern. A vulnerable package isn't always exploitable in a given app. We don't name any app.