Same CVEs, Different Days: Why Some Teams Patched in Two Hours and Others Opened a War Room

On October 21st, 2026, three of the most widely used runtimes shipped critical security fixes on the same day:
- PHP released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical remote code execution bugs (CVE-2026-109618 and CVE-2026-109619, nicknamed PHP2Shell, CVSS 9.2). Under the right conditions, an unauthenticated attacker could run code on the server. On Apache with mod_php, that could happen before any application code ran.
- Node.js shipped security releases for 22.x, 24.x and 26.x. They included a Brotli decoder out-of-bounds write that allows remote code execution, TLS hostname-verification bypasses, and updated c-ares, OpenSSL, SQLite and Undici.
- Oracle published an out-of-band Java SE security alert (CVE-2026-91403, CVSS 9.1) covering Java SE and GraalVM. It is exploitable over the network with no authentication.
This morning, a friend at a company with more than 500 employees told me they're in a war room trying to patch everything. Meanwhile, someone I know at a much smaller startup had fixes shipped and everything patched in about two hours. Not two hours to set up a war room. Two hours to finish. Same vulnerabilities, very different days. Here's what I think explains the gap.
The Embargo Didn't Hold, and Next Time It Won't Either
Coordinated disclosure is supposed to give defenders a head start. This time, it fell apart.
According to the PHP Foundation, the CVE IDs started circulating online two days before the planned release, along with a wrong release time and an inflated severity score. The PHP project moved the release forward by a day. After the leak, one of the reporting security firms published a proof-of-concept video by mistake, and copies spread even after it was taken down. Then, more than six hours before the coordinated release, Chainguard published built images containing the fix, so anyone could study the patch while everyone else was still waiting.
The lesson isn't that one party failed. It's that your patching process can't depend on a perfect disclosure timeline. If you only get moving once the official release lands, you're already behind.
One Company, Three Very Different Customer Experiences
The Laravel team's response is the clearest illustration, because they run three products with three different ownership models:
Laravel Cloud: customers did nothing. Laravel put edge network mitigations in front of every region, then patched one region at a time, pausing deployments until every region was done. By the next day, every Cloud application had been patched automatically.
Laravel Vapor: the patched PHP runtime images were ready when the fix landed. Customers redeployed and were done.
Laravel Forge: customers had to update PHP on their own servers. And there was a trap here: as the Forge advisory explains, Forge's automatic security updates don't patch PHP. Forge installs PHP from a dedicated package repository, while Ubuntu's unattended upgrades only pull from Ubuntu's own security repository. Anyone who assumed "we have auto-updates on" was still exposed.
Same company, same vulnerability, same day. The difference was who owned the runtime and how standardized the platform was.
What Turns a War Room Into a Routine Tuesday
1. Have a written policy for languages and versions
Decide which runtimes you allow, which versions, and when each version is retired. Publish it, enforce it in CI, and review it on a schedule.
This matters most on days like yesterday. Oracle's alert only covers versions in Premier or Extended Support. PHP only patches its supported branches, and PHP 8.2 reaches end of security support on December 31st, 2026. If you're running something older, there's no official patch to apply. You have to wait on goodwill from other engineers who might be on vacation, ill or even burnt out, or you're stuck doing a migration under pressure.
When 40 services run nine PHP versions and six Node versions, you don't have one patch. You have fifteen investigations.
2. Be able to build runtime images from source
Official images often lag behind a security release by hours, sometimes longer. If your pipeline can build the runtime from the patched source tag, you aren't waiting on a registry.
You don't need to do this every day. You need it to work on the day you need it, which means it has to exist and be tested before then.
3. On bare metal or VMs, know exactly where every runtime comes from
Distro repository, vendor PPA, a third-party repo, Oracle's support portal, or a binary someone compiled years ago. Each source ships fixes on its own schedule, and some aren't covered by your automatic updates at all.
The Forge case shows exactly how this goes wrong. List every source for every runtime, and know how quickly each one usually publishes a fix.
4. Use one boring release process, owned by one team
Internal tools, customer-facing apps and public websites should all build and deploy the same way, through pipelines owned by a single platform or infra team.
Laravel Cloud customers had no war room because someone else owned that pipeline for them. In a large company, your platform team should play that role for every product team. When every app deploys differently, every emergency patch becomes its own project.
5. Remember that "patched" isn't the same as "running the patch"
Upgrading a package doesn't replace code that's already loaded in memory. Queue workers, Laravel Horizon, Octane, Reverb, Node processes under a process manager, and long-running JVMs all keep the old runtime until they restart.
Make the restarts part of your CI deployment, not a manual step someone has to remember on a bad day. Then have the pipeline confirm the version reported by the running process, not just the one on disk.
6. Keep an inventory you can query
You should be able to answer "which services run which runtime version, on which base image, and who owns each one" in minutes. An SBOM (software bill of materials, a machine-readable list of everything inside each build) makes this a search instead of an investigation. A service catalog or even an up-to-date spreadsheet also works. A morning of Slack or Teams threads asking "is anyone using PHP 8.3?" doesn't.
7. Have tests you trust on a bad day
Speed depends on confidence. If a runtime bump needs a week of manual QA, you're exposed for a week. A test suite good enough to ship on is a security control.
8. Upgrade in small steps, and practice the playbook
Teams that move up a minor version every month barely notice an emergency patch. Teams three major versions behind find out the fix doesn't exist for them.
Write down who decides, who patches, who communicates with customers and leadership, and what counts as "done." Then run through it once a quarter, while nothing is on fire.
Boring Is the Goal
None of this is exciting. There's no clever tool to buy and no heroics. That's the point. The teams that were done by lunchtime yesterday weren't faster because they worked harder that day. They were faster because of dull decisions made months earlier.
A Word for the Maintainers
PHP runs a huge share of the web, but its security work depends on a small group of funded engineers plus some volunteers. Node.js is also largely volunteer-maintained. If your business depends on these runtimes, fund them. Sponsoring the PHP Foundation or the OpenJS Foundation costs less than one war room.
How did your team handle October 21st?