On October 21, 2026 (14:01 UTC), the PHP development team released out-of-cycle security updates addressing two critical vulnerabilities in the PHP runtime that can lead to unauthenticated Remote Code Execution (RCE) with the privileges of the web worker account. The vulnerabilities are tracked as CVE-2026-109618 and CVE-2026-109619, and both are rated 9.2 (Critical) on the CVSS v4.0 scale:
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
The vector explains the score: the attack is network-reachable and requires no authentication or user interaction, but it is rated high complexity (AC:H) and has attack requirements (AT:P), so it falls short of the maximum. The “CVSS 10.0” figure that circulated before the release came from leaked, pre-disclosure reports. It is not the official PHP rating.
The community calls the issue “PHP2Shell.” The vulnerabilities reside in the PHP core, so the risk is not limited to a single content management system (CMS) or plugin. PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed (LSAPI) deployments must each be evaluated based on their version and configuration. The attack paths are not identical across these environments.
According to PHP’s official security advisories, the two vulnerabilities have distinct root causes:
Both vulnerabilities are fixed in the following versions:
| Branch | Affected | Fixed |
|---|---|---|
| 8.5 | < 8.5.12 | 8.5.12 |
| 8.4 | < 8.4.27 | 8.4.27 |
| 8.3 | < 8.3.36 | 8.3.36 |
| 8.2 | < 8.2.35 | 8.2.35 |
| 7.4 / 8.0 / 8.1 (EOL) | Affected | Source backports only (see Section 6) |
This article examines the root causes, exploitation conditions, how the risk differs between runtime environments, remediation, and detection and response steps for Blue Teams. The technical evaluation is based on the official PHP security advisories. The publication of Proof-of-Concept (PoC) code, demonstrations of successful exploitation, and observations of real-world attacks are treated as separate categories of evidence.
| Date / Time (UTC) | Event |
|---|---|
| Oct 20, 2026 | Details of the vulnerabilities leak ahead of coordinated disclosure (a now-deleted Hacker News post). Claims of “CVSS 10.0” and “PHP 5 and later” circulate. |
| Oct 20, 2026, ~19:33 | PHP publishes an advance notice of an out-of-cycle critical security release. |
| Oct 20, 2026 | CERT-EU publishes Security Advisory 2026-018. |
| Oct 21, 2026, 14:01 | PHP releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35 and publishes the GitHub security advisories. |
| Oct 21, 2026 | Distributions that received the patches in advance publish updates. For example, Ubuntu publishes USN-8948-1. |
| Oct 22, 2026 | Originally planned coordinated disclosure date. |
When it processes a web request, PHP manages request data, error state, session state, and various internal object and extension states. The lifecycle of these data structures must be controlled carefully, especially in long-running worker processes such as PHP-FPM children and Apache mod_php workers, which serve many requests in succession.
Freeing the memory allocated to a request when it terminates is not enough. Global or process-level references that subsequent requests might access must also be left in a valid state. Likewise, if PHP’s error handling aborts processing because a memory allocation failed, any partially built state must be safely sanitized afterward.
These two vulnerabilities show the security impact of two different lifecycle flaws: one in memory management and error handling, the other in cross-request state handling. Both can be triggered before any application code runs, so application-level security controls, including CMS and plugin updates, cannot prevent them.
Weakness classes: CWE-416, CWE-755, CWE-824, CWE-1325, CWE-1419
PHP uses longjmp() to leave the current execution context when it runs out of memory (OOM). This vulnerability is caused by that mechanism.
In certain execution contexts, request memory becomes reachable before all its internal fields are initialized. If a memory allocation fails during this window, the early exit leaves the request’s internal state inconsistent. Request shutdown can then read uninitialized or invalid data, or branch on corrupted values.
The failed allocation does not have to be directly related to the corrupted data. The core problem is that an OOM event disrupts control flow, and the lifecycle of request memory is not managed correctly across that disruption.
The advisory notes that several attacker-controlled strategies can drive PHP into the OOM condition. Most of them involve the multipart/form-data request body parser, which runs during request startup before any application code:
post_max_size check and keep supplying decoded body data.max_file_uploads but still create file metadata arrays. Nested field names multiply this work.memory_limit, and shutdown then processes the invalid state. According to the advisory, a full remote exploit was validated over HTTP against mod_php with default settings, and no application-specific code is needed to reach the path.Risk assessments for these environments must be based on the exact version and runtime model in use.
Remediation approach: PHP removed the longjmp()-based early exit for OOM conditions. It replaced it with two mechanisms. A delayed soft OOM is handled gracefully at the next safe virtual machine instruction point. A hard OOMterminates the process immediately (_exit()) if memory usage reaches a second, higher threshold. Normal memory_limit enforcement is kept. The goal is to make sure teardown routines never act on partially initialized memory.
Weakness classes: CWE-416, CWE-755, CWE-824, CWE-1325, CWE-1419
The second vulnerability arises because global state kept in a running worker process can still hold references to a request’s memory after that memory has been freed.
PHP keeps several kinds of internal state in the running process, including error, session, object and extension state. Some of these can point into memory owned by a single request. When the request ends, that state must be reset. Two things can break this:
If the next request touches this stale state before normal initialization resets it, a Use-After-Free (UAF) condition occurs. The advisory lists heap use-after-free, memory disclosure, and RCE with the web worker’s privileges as possible impacts.
According to the advisory, exploitation requires two components, a producer and a consumer, that run in the same worker process:
The producer and the consumer can be different HTTP requests. Running multiple workers and recycling them more often lowers the probability of success, but neither removes the underlying condition.
The official advisory identifies two main consumer paths that access stale global state before normal request initialization:
php_request_startup() can touch stale error state. The message does not have to be displayed or logged. error_reporting settings, the @ operator, and disabling display_errors or log_errors do not preventthis..htaccess, php_value / php_flag, and Apache directives) that is evaluated before request initialization.PHP_VALUE or PHP_ADMIN_VALUEFastCGI parameters. Pool configuration and .user.ini files are evaluated differently and do not provide the same early consumer.session.upload_progress.enabled) is enabled by default, and the application does not need to call session_start().fatal_error_backtraces (strongest case): Backtrace state generated during fatal error reporting can persist in global state after request memory is freed. Early diagnostics in a later request can then access it. This is the basis of the confirmed RCE against mod_php.Remediation approach: PHP implemented a broader cleanup that systematically clears the relevant global state beforerequest memory is freed. The goal is not only to close the known consumer paths but to secure the lifecycle of any stale state that a later request could otherwise reach before normal initialization.
| CVE-2026-109618 | CVE-2026-109619 | |
|---|---|---|
| Bug class | Control-flow disruption on OOM, leaving partially initialized request memory | Stale global reference (UAF) that crosses request boundaries |
| Typical trigger | Memory exhaustion during request startup (multipart parsing) | Producer request (fatal/OOM/timeout) followed by a consumer request on the same worker |
| Strongest validated case | mod_php, default settings | mod_php (8.5 fatal backtraces); session upload progress on mod_php and FPM |
| FPM | Full exploit not demonstrated | Validated via session upload progress |
| Fix | Removal of longjmp() on OOM; soft and hard OOM | State reset before request memory is freed |
The two issues are independent at the code level, but they reinforce each other in practice. An attacker-induced OOM is both the trigger for CVE-2026-109618 and a demonstrated producer for CVE-2026-109619. Mitigations that reduce attacker-controlled memory exhaustion therefore reduce exposure to both. The fixes differ, and each must be verified separately.
These vulnerabilities affect PHP runtimes that process web requests and can be triggered before application code runs, so the theoretical attack surface is very large. Still, the fact that an application is built with PHP does not prove that exploitation is possible. The actual risk depends on the running version, the SAPI, the configuration, and whether the specific attack paths are reachable.
The following environments need particular attention:
Official PHP advisories confirm a validated exploit for CVE-2026-109618 on mod_php. For PHP-FPM, source analysis supports theoretical exploitability, but no complete exploit has been demonstrated. For CVE-2026-109619, validated impact has been demonstrated through the fatal backtrace path on mod_php (PHP 8.5) and through the session upload progress path on both mod_php and PHP-FPM. For FrankenPHP and LSAPI, theoretical likelihood must be kept separate from verified exploit evidence.
For PHP-based platforms such as WordPress, Drupal, Joomla, Magento, Laravel and Symfony, the first step is to identify the exact PHP runtime version and the SAPI that actually serves requests, rather than listing application names. Updating a CMS or plugin does not replace patching the PHP core, and application-level security plugins such as WordPress WAF plugins cannot inspect a request before PHP’s core parses it.
Potential impacts of successful exploitation include:
wp-config.php and .env files.These are the theoretical bounds of RCE impact. They do not mean every outcome is possible in every PHP environment because of these CVEs.
Before the patches were disclosed, reports circulated about leaked exploit tooling and technical details under the name “PHP2Shell”. A short exploitation demonstration video was briefly posted and then removed. watchTowr stated that it had reproduced CVE-2026-109618 and confirmed that the vulnerabilities were real. After the release, the official PHP advisories documented successful remote code execution and validated attack paths on specific runtimes.
Three types of evidence must be kept separate:
Status at the time of writing (October 21, 2026, ~15:30 UTC):
| Evidence type | Status |
|---|---|
| Vendor-validated exploitation | Yes. PHP advisories describe validated RCE on mod_php (both CVEs) and on PHP-FPM (CVE-2026-109619, session upload progress path). |
| Public PoC code | Repositories claiming to contain PoC code have appeared on GitHub. None has been independently verified. Tenable has also warned that unverified exploit code is sometimes laced with malware. |
| In-the-wild exploitation | Early reports, not yet broadly confirmed. Cloudflare stated it is seeing early attacks and has deployed WAF rules for known vectors. Huntress and watchTowr had not observed exploitation in their telemetry as of their latest updates. Patchstack’s claims of active incidents had not been backed by published evidence. |
| CISA KEV | Not listed at the time of writing. |
The existence of a PoC repository does not prove that RCE is achievable in every environment. Some scripts only reach a specific error path, and others may be broken or malicious. The official advisories confirm exploitation for specific attack paths, but that does not mean every public PoC is reliable or that every PHP installation is exploitable out of the box. Exploit reliability depends on the PHP build, the loaded extensions, the frontend, and the allocator layout.
Claims of active exploitation must likewise be judged by their source, timeline and supporting evidence. Seeing scan attempts in one organization does not mean every PHP system is equally targeted. Conversely, finding no exploitation in a given environment does not prove that environment is secure.
PoC code must never be run against production environments. If analysis is needed, it must be done in isolated, controlled lab environments.
On October 21, 2026, the PHP development team released the following security versions, which fix both vulnerabilities:
According to PHP, updating is the only complete fix. Interim mitigations reduce exposure but do not make an installation safe. PHP 8.2 reaches end of life on December 31, 2026.
Linux distributions and LTS vendors received the patches in advance. Many distributions backport fixes without changing the upstream version string, so the visible version alone (php -v) cannot be used to judge whether a system is patched. Always check the full package version and the vendor’s security bulletin.
| Distribution | Fixed package (example) | Notes |
|---|---|---|
| Ubuntu 24.04 LTS | 8.3.6-0ubuntu0.24.04.13 | USN-8948-1. The version string stays 8.3.6. |
| Ubuntu 22.04 LTS | 8.1.2-1ubuntu2.28 | USN-8948-1. PHP 8.1 is EOL upstream but patched by Canonical. |
| Ubuntu 26.04 LTS | 8.5.4-0ubuntu1.5 | USN-8948-1 |
| Debian, RHEL and derivatives | Check DSA/DLA and RHSA | Backported fixes, version strings may not change |
On Ubuntu and Debian, the package changelog (/usr/share/doc/<package>/changelog.Debian.gz) can be searched for the CVE identifiers to confirm that the fix is installed.
Mirror lag: Some hosting providers’ local package mirrors can lag behind the official security archive by hours. If the vendor bulletin lists a fixed version that apt/dnf does not yet offer, configure the vendor’s primary security repository directly (for example security.ubuntu.com for Ubuntu) instead of switching to a third-party repository.
Third-party repositories: The volunteer-maintained rpms.remirepo.net repository did not have updates on release day. PHP advised its users to switch to distribution packages or build from source.
PHP 8.1 and older branches no longer receive regular security support. The PHP security team published minimal source backports on the following branches for users who build from source or have no LTS vendor:
PHP-7.4-CVE-2026-109618-109619PHP-8.0-CVE-2026-109618-109619PHP-8.1-CVE-2026-109618-109619Operating system distributions and LTS vendors may ship their own patched packages for these branches. Decisions about legacy systems must not rely on version numbers alone. Check the vendor’s security advisories directly, and plan a migration to a supported branch.
Checking the version reported by the command-line interface (php -v) is not enough. The CLI binary and the runtime that serves web requests (PHP-FPM, the Apache module libapache2-mod-php/mod_php, or another SAPI) are often separate packages with separate configuration files. You must verify that the SAPI actually serving traffic runs the patched binaries.
phpinfo() page that is removed afterward, and check core application functionality.If patches cannot be applied immediately, configuration changes and network controls can reduce exposure. These measures do not provide complete protection and are not a substitute for the official patches. PHP states that no complete, generic configuration-based mitigation exists.
The official interim configuration from the PHP security announcement:
; php.ini or FPM pool / Apache config, applied before request parsing
memory_limit = -1 ; set via php_admin_value so apps can't override
post_max_size = 8M ; 32M if file uploads are required
session.upload_progress.enabled = 0 ; restart all workers afterwards
fatal_error_backtraces = 0 ; PHP 8.5 only; restart all workers afterwardsAll of these must be applied at the administrative level, such as php.ini, php_admin_value/php_admin_flag in FPM pools or the Apache configuration. All workers must then be restarted. Application-level mechanisms such as ini_set(), and per-directory overrides, should not be relied on.
memory_limit = -1 is the main configuration workaround. It removes the predictable per-request memory-limit exhaustion that the validated attack path relies on. It is not complete, because system-level allocation failures (for example from mmap()) can still reach the vulnerable longjmp() path. Requirements:
php_admin_value). No pool, directory or application setting may restore a finite limit.memory.max) that preserves service availability. Evaluate it against available hardware before rolling it out.Warning: PHP explicitly advises against using
RLIMIT_ASorRLIMIT_DATAprocess limits as the boundary. They makemmap()fail when reached and so trigger the very allocation-failure path they are meant to defend against.
Additional hardening (reduces OOM and DoS risk but does not replace updating):
post_max_size conservative (8M, or 32M where uploads are required), and keep upload_max_filesize consistent with it.LimitRequestBody in Apache, client_max_body_size in nginx, or WAF limits.max_input_nesting_level and bound the number of input variables (max_input_vars).multipart/form-datarequests at the frontend. Otherwise restrict them to the specific upload endpoints and trusted sources.To remove the specific validated producer and consumer paths on unpatched systems, the official guidance recommends:
session.upload_progress.enabled = 0: Removes the validated session upload progress consumer path (mod_php and FPM). PHP recommends keeping this disabled even after patching if the feature is not needed. Few applications use it, and WordPress core does not.fatal_error_backtraces = 0 (PHP 8.5 only): Removes the confirmed RCE producer used in the mod_php demonstration..htaccess files, Apache php_value/php_flag directives, and any PHP_VALUE/PHP_ADMIN_VALUE FastCGI parameters for invalid or deprecated INI settings that produce warnings or deprecations.pm.max_requests = 1 for PHP-FPM if performance allows, so that a worker never serves a second request with stale state.log_errors, set a working error_log, and use error_reporting = E_ALL to find warnings and fatal errors. Clean logs do not prove safety.These controls cover only specific vectors. They do not mitigate every INI diagnostic path, other global state, other error-handling paths, or extension-specific vectors.
The permanent solution for both CVEs remains upgrading to the patched PHP versions or vendor packages.
HTTP access logs alone are not enough to detect exploitation of these vulnerabilities. Access logs must be correlated with PHP error logs, web server error logs, process behavior telemetry, file system changes, and network activity.
Investigate the following:
multipart/form-data POST requests, especially to endpoints that do not normally accept uploads. Look for unusually large part or header counts, many empty file fields, deeply nested field names, missing or inconsistent Content-Length, and bodies containing a PHP_SESSION_UPLOAD_PROGRESS field.Allowed memory size of ... bytes exhausted fatal errors, particularly during request startup or POST parsing.child pid ... exit signal Segmentation fault (11). In PHP-FPM it appears as child ... exited on signal 11 (SIGSEGV).max_execution_time or request_terminate_timeout events from the same sources.None of these indicators proves exploitation on its own. Legitimate file uploads and traffic spikes can produce similar patterns, so correlate them with the timeline and other telemetry.
Query EDR and process monitoring systems for PHP worker processes that spawn unexpected child processes. Shells, system binaries (sh, bash, nc, wget, curl) and script interpreters (python, perl) started directly by PHP-FPM, php-cgi, Apache or other web server workers require immediate triage. Command lines containing reverse-shell patterns (such as /dev/tcp/, mkfifo) or reconnaissance commands (id, whoami, uname -a) are high-signal.
Some legitimate PHP applications run external system commands, so normal application behavior must be taken into account. Process trees, command-line arguments, user contexts, timestamps, and the corresponding HTTP requests must be evaluated together.
Key forensic artifacts to inspect during incident response:
.php files in upload directories such as wp-content/uploads/..htaccess files, and file permissions.At the time of writing, no authoritative, CVE-specific indicators of compromise (IOCs) such as attacker IP addresses, domains or file hashes had been published. Payloads can vary widely, so broad behavioral indicators should not be presented as CVE-specific IOCs unless verified incident reports or trusted threat intelligence support them.
If successful exploitation is suspected:
Applying the patch does not remove artifacts left by an earlier successful compromise, such as webshells, persistence mechanisms or stolen credentials. A suspected security event must not be closed simply by upgrading. A full incident response triage must be performed.
CVE-2026-109618 and CVE-2026-109619 are critical vulnerabilities in the PHP core. Under specific runtime conditions they allow unauthenticated remote code execution before any application code runs. The CVSS v4.0 score of 9.2, validated exploitation on Apache mod_php (and on PHP-FPM for CVE-2026-109619), the leak before disclosure, and early reports of attacks all make rapid, systematic remediation essential.
Technically, CVE-2026-109618 comes from control-flow disruption and partially initialized request memory during OOM handling. CVE-2026-109619 comes from stale global state that persists across request boundaries in the same worker. The two issues reinforce each other in practice, because attacker-induced memory exhaustion is a trigger for the first and a demonstrated producer for the second.
For organizations, the immediate priority is to inventory every PHP installation, deploy the appropriate upstream or vendor security updates, and verify that the SAPI actually serving web traffic runs patched binaries. Distribution backports usually keep the upstream version string, so verification must be based on package versions and vendor bulletins. Temporary configuration changes and network controls reduce exposure, but they must not be treated as permanent fixes. Disabling session.upload_progress is still worthwhile after patching if the feature is not used.
For Blue Teams, knowing that the vulnerabilities exist is not enough. Correlating request logs with web server crash signals, process behavior, file system integrity, and network telemetry is essential for detecting exploitation attempts and limiting their impact.
PHP2Shell is a critical security event that requires coordinated patch management and proactive threat hunting. Security decisions must be based on verified technical findings and current vendor advisories, and PoC claims, active exploitation reports, and IOCs must each be kept separate according to the evidence behind them.
Running PHP in production and unsure whether you are exposed? Our External Penetration Testing identifies the exact PHP runtime, SAPI and configuration serving your requests and the attack paths that reach them, our Managed Security Services hunt for the post-exploitation behavior described above, and our Incident Response Tabletop Exercisesprepare your team for a fast-moving disclosure like this one. Talk to our team.
Note: This article is based on the PHP security advisories published on October 21, 2026 and on public reporting available as of approximately 15:30 UTC that day. Distribution packages, exploitation reports and IOCs are changing rapidly. Verify the current status in the respective vendor sources before publication.