On October 21, the PHP project released emergency fixes for two flaws tracked together as PHP2Shell: CVE-2026-109618 and CVE-2026-109619. According to BleepingComputer and Help Net Security, both are unauthenticated remote code execution bugs in PHP core, rated 9.2 on CVSS v4.0 by the PHP security team (Wiz describes the severity more cautiously, so ratings are not uniform across vendors). The fixed versions are 8.5.12, 8.4.27, 8.3.36 and 8.2.35.
We have not read the PHP advisory line by line ourselves, and several details below come from secondary vendor write-ups. Verify against php.net before acting. The operational lessons, though, do not depend on the fine print.
What is reported about the bugs
Based on the coverage we could find:
- CVE-2026-109618 is described as an out-of-memory condition that triggers a
longjmp(), interrupting request handling while internal request data is only partly initialized. - CVE-2026-109619 is described as a stale-global-state problem leading to a heap use-after-free, with memory disclosure and code execution possible. It is associated with the
session.upload_progressfeature. - Anything that serves web requests is in scope: PHP-FPM, Apache with
mod_php, FrankenPHP. Reports single outmod_phpas the highest risk. - Disclosure details reportedly leaked before the embargo ended, and the release was moved up by a day. Whether exploitation in the wild is confirmed is disputed between vendors, so plan as if it is.
Step 1: Find every PHP runtime you operate
The painful part of an event like this is rarely the patch itself. It is the inventory. PHP hides in places teams forget:
- Base images (
php:8.3-fpm,wordpress,drupal) pinned by digest months ago - Legacy VPS boxes running distro packages
- Staging and preview environments
- Client-managed servers you host or advise on
For containers, query what is actually deployed rather than what the Dockerfile says:
# Print the PHP version inside each running container that has php installed
for c in $(docker ps --format '{{.Names}}'); do
v=$(docker exec "$c" php -r 'echo PHP_VERSION;' 2>/dev/null) && echo "$c $v"
doneFor Kubernetes, the same idea with kubectl exec over a label selector works, but an image scan (Trivy, Grype) against your registry gives a broader view with less effort.
Step 2: Patch in risk order
Prioritize by exposure, not by team ownership:
- Internet-facing runtimes, especially
mod_phpon Apache - Internet-facing PHP-FPM behind nginx or a CDN
- Internal tools reachable by many users
- Everything else
If you are on a supported branch, the upgrade is a patch-level bump and normally low risk:
# Before
FROM php:8.3.30-fpm-alpine
# After
FROM php:8.3.36-fpm-alpineRebuild with --pull so you do not reuse a cached base layer, then confirm inside the running container with php -v.
The end-of-life problem
PHP 8.1 and older no longer receive upstream updates. Reports say the security team published minimal source backports for 7.4, 8.0 and 8.1, and some distributions and LTS vendors ship their own. Bitsight's data, as quoted in the coverage, suggests only about a third of version-identifiable PHP hosts run a patched branch, with 7.4 the most common branch.
If you run an EOL branch, you have three real options: take the vendor backport, upgrade the branch (a project in its own right), or put the application behind controls that reduce exposure while you do. We would treat "we'll upgrade next quarter" as unacceptable here for anything internet-facing.
Interim mitigations: use with care
Secondary sources suggest these stopgaps. None replaces the update:
- Set
session.upload_progress.enabled=0if you do not use it. This relates to CVE-2026-109619, and some sources recommend leaving it off after patching too. - For CVE-2026-109618, one source recommends an administrative
memory_limit=-1across all pools, with a warning not to substituteRLIMIT_AS. That advice is counterintuitive and we would only apply it after reading the PHP advisory, because removing memory limits has its own denial-of-service consequences. - Blocking
multipart/form-dataat the proxy for apps that never accept uploads.
; php.ini or a pool-level override
session.upload_progress.enabled = 0Treat these as time buyers measured in hours, not a posture.
After patching
- Restart workers. PHP-FPM and Apache keep old code in memory until reloaded.
- Check access logs for unusual multipart requests to endpoints that do not take uploads in the days before you patched.
- If you find suspicious activity, rotate secrets stored on that host (database credentials, API keys,
.envcontents).
Takeaways
- Know your PHP inventory before the next advisory arrives. A scheduled job that records
PHP_VERSIONper workload pays for itself. - Patch internet-facing
mod_phpfirst. - EOL branches are a risk decision, not a backlog item.
- Verify vendor-reported mitigation details against the official advisory before changing production configuration.