Caption: composer show first. Then composer audit --locked. Then the space-split lab. Illuminate always pulls symfony/http-foundation. Do not stop at 7.4.19.
I did not send a crafted Cache-Control header at anything tonight. I opened Ubuntu 24.04 archive PHP 8.3.6 (php -v built 19 Oct 2026, package 8.3.6-0ubuntu0.24.04.13) and ran throwaway composer require of two tags. HeaderUtils::split('foo bar', ' ') on 7.4.19 returned one part. The same call on 7.4.21 returned two. composer audit on 7.4.19 printed No security vulnerability advisories found.
That is the wall this week. Packagist treats the first ReDoS tag as patched. The whitespace-separator follow-up is a later tag. Laravel 13.38.0 (20 Oct 2026) still requires symfony/http-foundation: ^7.4.0 || ^8.0.0. This is a Composer component CVE. It is not laravel/framework. composer why symfony/http-foundation on a Laravel 13 tree points at Illuminate. On this blog’s lib/ it printed Package not found — Spatie pulled yaml, not HttpFoundation.
What changed
Symfony’s CVE blog is dated 15 Oct 2026. GHSA-r925-mgvr-h9cc published the same day. Package: symfony/http-foundation. CVSS 8.7 High (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N). CWE-1333. Availability only. Unauthenticated.
What I will treat as locked this week:
HeaderUtils::split()was the engine. The token alternative also matched whitespace, then a(?<!\s)lookbehind. A run of spaces before a separator could be divided in exponentially many ways.HeaderBagcalls that splitter forCache-Controlwhenever aRequestis built, so a 404 still does the work. Advisory timing: 813 ms for 17 spaces in an 8 KB header on PHP 8.5, doubling with each extra space. From 18 spaces,preg_match_all()hitspcre.backtrack_limitandsplit()returns an empty array — every directive of the header is silently dropped. My CLIpcre.backtrack_limitis 1000000. I did not reproduce the 813 ms. I did not paste that header.- First ReDoS tags are not the floor I would install. Affected (GHSA):
>=4.1.0 <5.4.54,>=6 <6.4.46,>=7 <7.4.19,>=8 <8.1.7. Patched in that advisory’s table: 5.4.54 / 6.4.46 / 7.4.19 / 8.1.7. Packagisttimeon those first 6.4/7.4/8.1 tags is 14 Sep 2026. Packagist advisory PKSA-xmwy-rmx5-m7h4 still ranges<7.4.19/<6.4.46/<8.1.7/<5.4.54. That is whycomposer auditgoes quiet on 7.4.19. - The first fix broke splitting on a space. Official resolution:
HeaderUtils::split('foo bar', ' ')returned a single value in 6.4.46–47, 7.4.19–20, 8.1.7–8. Whitespace used as a separator is left out of the whitespace branch in 6.4.48 / 7.4.21 / 8.1.9. Symfony blogs for those three tags: 14 Oct 2026. GitHub: v6.4.48 14 Oct 06:43 UTC, v7.4.21 06:46, v8.1.9 06:49. PRs #66048 and follow-up #66491. - 5.4.54 ships both PRs in one tag. GitHub v5.4.54 is 15 Oct 2026 06:52 UTC (
#66048and#66491). Packagisttime2026-09-30T11:07:08+00:00 (git). No 5.4.55 I can cite. - CVE record 15 Oct 2026 14:46:01Z (cve.org). NVD 15 Oct 2026 15:17:22 UTC. OSV modified 21 Oct 2026. Packagist still has no 8.1.10 / 7.4.22 / 6.4.49. 8.1.9 needs PHP >= 8.4.1; this 8.3.6 box cannot take it. The 7.4 line is PHP >= 8.2.
- Laravel always pulls this package. laravel/framework 13.38.0 requires
symfony/http-foundation: ^7.4.0 || ^8.0.0. Not a Laravel-core CVE. A CodeCanyon leftover on Laravel 12 will still have the component.composer showis the check, not a Slack thread that says “Laravel is owned.”
What I will treat as rumor: Illuminate having a CVE (composer show laravel/framework is the wrong package); stopping at 7.4.19 because audit is green (my lab: audit clean, split still one part); apt upgrade on Ubuntu 24.04 fixing this (distro PHP is still 8.3.6; HttpFoundation is Composer); Symfony 8.2 as a GA I can pin (forward-ported in the advisory, Packagist still 8.2.x-dev).
Same-week siblings, only if the lock has them: YAML CVE-2026-109413 (floors 5.4.54 / 6.4.45 / 7.4.18 / 8.1.6) and ExpressionLanguage CVE-2026-109449 (complete in 5.4.54 / 6.4.48 / 7.4.21 / 8.1.9). A Week of Symfony #1033 listed all three. This blog’s lib/ pulled yaml 7.4.21 via Spatie and has no http-foundation. I asked composer show. That is not a Laravel app.
What I would change in a real Laravel/PHP app this week
Three edits. None of them is “paste a Cache-Control header at production.”
1. Prove the lock. Then run the space-split lab. Do not send a ReDoS payload.
php -v
php-fpm8.3 -v # the pool Nginx uses, not the CLI I wish I had
composer show symfony/http-foundation
composer why symfony/http-foundation
composer audit --locked
composer audit talks to Packagist by default. --locked reads composer.lock. Exit 0 means no policy hits. Exit 1 means it found something, or a required package is missing. Composer 2.10.3 (27 Aug 2026) refused to install 7.4.18 here because of PKSA-xmwy-rmx5-m7h4. It was happy to install 7.4.19. Then audit on 7.4.19 was green. That is the miss.
Then the before, on the binary that actually served the last request:
use Symfony\Component\HttpFoundation\HeaderUtils;
$parts = HeaderUtils::split('foo bar', ' ');
var_export($parts);
echo 'count=', count($parts), PHP_EOL;
On this box that printed:
PHP 8.3.6 (cli) (built: Oct 19 2026)
# throwaway composer require symfony/http-foundation:7.4.19
array (
0 => 'foo bar',
)
count=1
# same tree, 7.4.21
array (
0 => 'foo',
1 => 'bar',
)
count=2
Two parts is the complete fix. One part is the first-fix regression. I would not put 17 spaces into a header to “see the 813 ms.”
2. Bump to the complete floor for the line I actually lock. Reload FPM.
# PHP 8.3 VPS — Laravel 13 will resolve the 7.4 line.
composer update symfony/http-foundation --with-dependencies
composer show symfony/http-foundation
# versions : * v7.4.21
# PHP 8.4+ only — 8.1.9 requires >=8.4.1
# composer show will print v8.1.9 when the platform allows it
sudo systemctl reload php8.3-fpm
As of 23 Oct 2026 I still want 7.4.21, 6.4.48, 8.1.9, or 5.4.54. I would not stop at 7.4.19 / 6.4.46 / 8.1.7. I would not invent 8.1.10.
3. Gate any leftover that constructs a Request on an old lock. Do not call this a Laravel CVE.
use Composer\InstalledVersions;
use Symfony\Component\HttpFoundation\Request;
function httpFoundationCompleteFloorMet(): bool
{
if (! InstalledVersions::isInstalled('symfony/http-foundation')) {
return false;
}
$v = ltrim(InstalledVersions::getPrettyVersion('symfony/http-foundation'), 'v');
return match (true) {
str_starts_with($v, '8.') => version_compare($v, '8.1.9', '>='),
str_starts_with($v, '7.') => version_compare($v, '7.4.21', '>='),
str_starts_with($v, '6.') => version_compare($v, '6.4.48', '>='),
str_starts_with($v, '5.') => version_compare($v, '5.4.54', '>='),
default => false,
};
}
// Before — every hit built a Request, including 404, including healthchecks.
// $request = Request::createFromGlobals();
// After — brake until the lock is on a complete tag. The patch is Composer, not this if.
if (! httpFoundationCompleteFloorMet()) {
abort(503, 'HttpFoundation below CVE-2026-108082 complete floor.');
}
$request = Request::createFromGlobals();
That 503 is a brake. The patch is the lockfile. If I am already on 7.4.21 I delete the gate. I would still composer show symfony/yaml and composer show symfony/expression-language once. Absent packages are not those CVEs. Present ones need yaml 7.4.18+ and expression-language 7.4.21 on this line.
What would bite on a self-hosted VPS
Caption: composer show then composer audit --locked. Then HeaderUtils::split('foo bar', ' '). Two parts is the complete fix. One part is 7.4.19. Do not send Cache-Control at a live app.
First bite: audit green, lock still on 7.4.19. Packagist’s range ends at the first ReDoS tag. CI that only checks composer audit --locked will ship the regression. The space-split is two arguments, not a network request.
Second bite: PHP 8.3 vs 8.4 on the same app. Laravel 13 advertises 8.3–8.5. 8.1.9 will not install on this 8.3.6 CLI. config.platform.php set to 8.4 on a laptop, and FPM still on 8.3, is how I get a lock the VPS cannot install. CI that resolves against 8.4 and deploys to 8.3 will fail on the VPS, or worse, never run composer install there and keep serving laptop vendor/. The error I actually expect:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires php >=8.4.1 (because 8.1.9 said so)
I would pin the 7.4 line on an 8.3 box: composer require "symfony/http-foundation:^7.4.21". I would not invent that apt will give me PHP 8.4 this afternoon.
Third bite: shared hosting and leftover vendor/. If the panel will not let me composer update, I do not edit HeaderUtils.php in place. There is no userland polyfill for this advisory on a shared-hosting panel that blocks Composer. Rsync an old vendor/ after a green laptop audit and FPM still runs 7.4.19. OPcache keeps the old class until I reload the pool Nginx actually uses.
Eight days after the advisory
Caption: First ReDoS tags 14 Sep 2026. Complete floors GitHub-released 14 Oct. GHSA and CVE record 15 Oct. I am writing 23 Oct. Packagist still has 8.1.9 / 7.4.21 / 6.4.48 as latest. No 8.1.10.
Symfony’s 6.4 page still lists 6.4.48 as latest 6.4, bug fixes until November 2026, security until November 2027 (retrieved 23 Oct 2026). Honest target this week: Laravel 13 on PHP 8.3 FPM, lock on http-foundation 7.4.21, split('foo bar', ' ') returning two parts, CLI and the socket on the same PHP. If the box is already 8.4, 8.1.9. I would not invent the next Thursday tag today.
Are you on this in production?
If composer show symfony/http-foundation already prints 7.4.21 (or 6.4.48 / 8.1.9 / 5.4.54 on that line) and HeaderUtils::split('foo bar', ' ') returns two parts, you are on this. If audit is green and the lock still says 7.4.19, you are not — that is the first-fix tag Packagist already considers patched. If CLI shows 7.4.21 and the deployed vendor/ is still 7.4.18, you are not. Shared hosting that will not run Composer is the fourth camp. I did not flip a client cluster tonight. I want to know which of those you are in.
Did you hit the same wall?
I would get stuck on composer audit exit 0 on 7.4.19 while split('foo bar', ' ') still returned one part, or on Composer blocking 8.1.9 because this VPS is PHP 8.3.6. Did you hit the same thing, or a different one — a lock that jumped to Symfony 8 on a laptop with 8.4, a host that will not let you update vendor/, yaml present and http-foundation already bumped? Tell me in the comments. I read them.
If the blocker is the VPS itself (wrong PHP floor, a panel that will not run Composer, a socket that still loads old vendor/), I do this class of bump for a living: Hire for deploy.
References
- Symfony CVE-2026-108082 blog (15 Oct 2026): https://symfony.com/blog/cve-2026-108082-redos-in-headerutils-split-reachable-through-the-cache-control-request-header
- GHSA-r925-mgvr-h9cc (published 15 Oct 2026), CVSS 8.7,
symfony/http-foundation: https://github.com/symfony/symfony/security/advisories/GHSA-r925-mgvr-h9cc - CVE Record CVE-2026-108082 (2026-10-15T14:46:01Z): https://www.cve.org/CVERecord?id=CVE-2026-108082
- NVD CVE-2026-108082 (published 15 Oct 2026 15:17:22 UTC): https://nvd.nist.gov/vuln/detail/CVE-2026-108082
- OSV CVE-2026-108082 (modified 2026-10-21T02:50:18Z): https://osv.dev/vulnerability/CVE-2026-108082
- Packagist advisory PKSA-xmwy-rmx5-m7h4 (
reportedAt2026-09-15; affected<7.4.19/<6.4.46/<8.1.7/<5.4.54): https://packagist.org/api/security-advisories/?packages[]=symfony/http-foundation - Symfony 6.4.48 released (14 Oct 2026): https://symfony.com/blog/symfony-6-4-48-released
- Symfony 7.4.21 released (14 Oct 2026): https://symfony.com/blog/symfony-7-4-21-released
- Symfony 8.1.9 released (14 Oct 2026): https://symfony.com/blog/symfony-8-1-9-released
- GitHub
symfony/http-foundationv8.1.9 (14 Oct 2026 06:49 UTC): https://github.com/symfony/http-foundation/releases/tag/v8.1.9 - GitHub
symfony/http-foundationv5.4.54 (15 Oct 2026 06:52 UTC;#66048and#66491): https://github.com/symfony/http-foundation/releases/tag/v5.4.54 - Packagist
symfony/http-foundation(8.1.9time2026-10-08T16:57:43+00:00; 7.4.21 2026-10-08T16:56:12+00:00; 6.4.48 2026-10-08T07:59:58+00:00; retrieved 23 Oct 2026): https://packagist.org/packages/symfony/http-foundation - Fix PR #66048: https://github.com/symfony/symfony/pull/66048
- Follow-up PR #66491: https://github.com/symfony/symfony/pull/66491
- Packagist
laravel/framework13.38.0 (2026-10-20;symfony/http-foundation: ^7.4.0 || ^8.0.0): https://packagist.org/packages/laravel/framework - Laravel 13 release notes (PHP 8.3–8.5, released 17 Mar 2026): https://laravel.com/docs/13.x/releases
- Composer
audit(--locked; exit 0 / 1): https://getcomposer.org/doc/03-cli.md#audit - YAML CVE-2026-109413 / GHSA-2v3c-qxhr-7vpv (published 15 Oct 2026): https://github.com/symfony/symfony/security/advisories/GHSA-2v3c-qxhr-7vpv
- ExpressionLanguage CVE-2026-109449 / GHSA-7rpj-w9pf-39rr (published 15 Oct 2026): https://github.com/symfony/symfony/security/advisories/GHSA-7rpj-w9pf-39rr
- A Week of Symfony #1033 (12–18 Oct 2026): https://symfony.com/blog/a-week-of-symfony-1033-october-12-18-2026
- Symfony 6.4 releases (6.4.48 latest; bug fixes until Nov 2026; retrieved 23 Oct 2026): https://symfony.com/releases