Free to list, always.No paid rankings. Every recommendation explains its trade-offs.
OpenSourceChoice
Security

PHP2Shell: Patch PHP, Then Prove Every Worker Restarted

PHP2Shell requires patched PHP packages and complete worker restarts. Use this rollout plan for supported, legacy, and container fleets.

Last reviewed
Evidence
3 official sources
PHPPHP2ShellCVE-2026-109618CVE-2026-109619securitypatchingPHP-FPMmod_phpcontainers
PHP2Shell: Patch PHP, Then Prove Every Worker Restarted

Patch every web-facing PHP runtime now, restart every worker, and verify the runtime actually serving traffic—not merely the package installed on disk. PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35 fix CVE-2026-109618 and CVE-2026-109619, two critical flaws collectively called PHP2Shell. A WAF or configuration change can reduce exposure while you deploy, but PHP's own advisory says only a fixed build is complete protection.

The right outcome is an evidence-backed inventory with zero unpatched workers, containers, or forgotten admin panels—not a ticket saying the update command succeeded. This assessment uses public information checked on October 23, 2026; OpenSourceChoice did not execute exploit code.

Why this matters now

PHP published the fixes on October 21 after details escaped coordinated disclosure. The official advisory became a top Hacker News story, while separate Reddit discussions among security and hosting operators focused on scanning, backports, and hosts without patched packages.

PHP lists PHP-FPM, Apache mod_php, php-cgi, FrankenPHP, and LiteSpeed as affected. Risk is highest for mod_php, where a request can reach the vulnerable path before application code runs. PHP-FPM is not a free pass: upstream validated a stale-state path involving an application-stage fatal error and a later request on the same worker.

These are runtime defects, not plugin bugs. An updated application can still use a vulnerable interpreter.

What the patches do—and what they do not prove

CVE-2026-109618 concerns out-of-memory handling during request processing. The patch replaces the unsafe early exit with controlled soft and hard out-of-memory behavior so shutdown cannot consume partially initialized request state. CVE-2026-109619 resets a wider set of request-owned global state before a later request can reuse stale memory.

Installing those fixes does not prove that:

  • every web pool loaded the new runtime;
  • a long-running Apache or FPM worker restarted;
  • a container was rebuilt from a fixed base image;
  • a distro's older-looking version lacks a security backport;
  • the system was not probed or compromised before remediation.

Treat package deployment, process replacement, and historical review as separate checks. As in a disciplined OpenSSH security rollout, verify patch state on the real traffic path.

Choose the correct update path

EnvironmentComplete fixEvidence to retain
Upstream PHP 8.2-8.5Move to 8.2.35, 8.3.36, 8.4.27, or 8.5.12Runtime version, package/source provenance, worker start time
Distribution packageInstall the vendor security update, even when its version remains olderVendor advisory, package changelog, exact installed build
Official PHP containerRebuild from a patched version or digest and redeployNew image digest, running container ID, runtime version
PHP 8.1 or olderPrefer a supported branch; use a vendor backport only as a temporary bridgeBackport advisory or patch provenance plus a dated migration owner

PHP 8.1 and older receive no upstream releases. Minimal source backports for 7.4, 8.0, and 8.1 do not restore general support. The credible short-term alternative is a documented distribution or LTS-vendor backport—not an unchanged runtime behind a WAF.

Do not reject a vendor fix because php -v still shows an older branch number. Ubuntu, Red Hat, and other distributions routinely backport security changes without rebasing the language. Verify the package build against the vendor advisory. Conversely, do not accept a recent build date alone as evidence; check that the package changelog or advisory names both CVEs.

Official PHP Docker tags for the four fixed FPM releases were published on October 21. Pulling a new tag is insufficient if production still runs the old image. Rebuild dependent images, replace containers, and compare the running digest with the approved artifact.

Operational cost, privacy, license, and maintenance

The software remains free under PHP's permissive Modified BSD/PHP License v4, identified by the project as BSD-3-Clause. There is no license change or new paid dependency in this response. The cost is operational: application regression tests, extension compatibility, a maintenance window, worker restarts, container rebuilds, and log review.

The update adds no telemetry or cloud service. Delaying risks code execution with the worker's access to files, environment variables, network services, and process-readable secrets. Least privilege limits impact but does not remove the flaw.

Maintenance signals are strong. The php/php-src repository was still receiving commits on October 23, publishes a security policy with private reporting channels, and issued detailed advisories naming reporters and remediation developers. Supported branches have fixed releases and official downloads; 8.2 reaches end of life on December 31, 2026, so an 8.2 emergency patch should include an 8.3-or-newer migration date.

The main failure mode: false closure

The most likely operational mistake is declaring success after updating files on disk while old workers continue serving requests. A package manager may not restart every SAPI. A blue-green deployment may leave one old pool behind. A sidecar, cron image, admin appliance, or bundled runtime may escape the inventory.

Temporary controls are useful only as time-boxed defense in depth. Upstream suggests disabling session upload progress and restarting every worker; PHP 8.5 operators can also disable fatal error backtraces. Request-size controls and WAF rules can block confirmed paths. None covers every producer and consumer of stale state, and upstream explicitly warns that configuration is not a complete mitigation. If no fixed build or trustworthy backport exists, remove the service from untrusted networks rather than extending the exception indefinitely.

Run a measurable canary, then close the fleet

Use one representative canary for each combination of SAPI, distribution or base image, PHP branch, and critical extension set.

  1. Inventory the runtime serving each hostname, including embedded admin tools and containers. Record SAPI, package or image source, active version, worker IDs, and owner.
  2. Capture baseline health: login, uploads, sessions, queues, scheduled jobs, error rate, and p95 latency. Do not test with public exploit code.
  3. Apply the fixed package or rebuild the image. Restart Apache, PHP-FPM, or the entire workload so no pre-patch worker survives.
  4. Verify from inside the running workload: fixed package or vendor backport, expected configuration, new worker start times, and the approved container digest.
  5. Run the same functional checks for 30 minutes. Require zero old workers, no new fatal errors, and no material regression in error rate or p95 latency before expanding.
  6. Roll out in bounded batches and keep a named exception list. Review access, web-server, FPM, and process logs for suspicious activity from the period before remediation.

The final gate is simple: every in-scope endpoint maps to a fixed runtime or a specifically isolated exception with an owner and deadline. For broader adoption evidence, reuse the maintenance and exit checks in the open-source project evaluation checklist.

Verdict

PHP2Shell justifies immediate action, but speed does not excuse weak proof. Patch supported branches, use vendor backports where necessary, rebuild containers, restart all workers, and verify the runtime that handles traffic. A WAF is a bridge; an old version string may still contain a valid backport; and an updated package with stale processes is not remediation.

Sources

Turn research into an architecture

Build a stack for this use case.

Answer nine practical questions and compare three transparent architectures with costs, free limits, lock-in, and migration paths.

Build my stack