PHP's Longjmp Bug: Inside CVE-2026-109618 and CVE-2026-109619

Two critical PHP flaws rated 9.2 allow unauthenticated remote code execution on any web server running the interpreter. Here is how the longjmp memory corruption actually works, who is exposed, and what to do now.

On 21 October 2026, the UK's National Cyber Security Centre issued an alert that is, by any measure, unusually blunt: a critical issue in PHP may allow attackers to execute commands on any web server running PHP. The two CVEs behind it — CVE-2026-109618 and CVE-2026-109619 — are rated 9.2 under CVSS 4.0, are remote code execution flaws, and have proof-of-concept code in circulation. If your estate touches the public internet, there is a very good chance PHP is somewhere in the blast radius.

Why this one is different

PHP vulnerabilities are routine. A deserialization bug in a framework, a path traversal in a plugin, an SQL injection in a CMS — these are the bread and butter of vulnerability management, and they are almost always scoped to a particular application, a particular module, or a particular configuration. CVE-2026-109618 and CVE-2026-109619 are not that. They live in the interpreter itself, in the machinery PHP uses to handle fatal errors and out-of-memory conditions. That means the exposure is not defined by which application you run, but by the fact that you run PHP at all.

That distinction matters enormously for how you respond. When a CMS plugin is vulnerable, you patch the plugin or disable it. When the runtime is vulnerable, every application on that runtime inherits the flaw — the customer portal, the internal wiki, the forgotten marketing microsite from 2019, the vendor appliance that quietly bundles a PHP stack nobody documented. The NCSC's guidance reflects exactly this: identify PHP installations generally, not just outdated ones.

Note: The NCSC explicitly states that organisations using any version of PHP are affected and should update to the latest fixed release. Do not assume a recent version is safe until the vendor advisory confirms the fix is present.

Anatomy of the two flaws

Both vulnerabilities trace back to longjmp(), the C library mechanism PHP uses to unwind the stack when a fatal error or an out-of-memory condition occurs. In normal operation this is a controlled bailout: something goes wrong, the interpreter jumps back to a known safe point, and the request is torn down cleanly. The bugs arise when that bailout happens at precisely the wrong moment, leaving internal state inconsistent.

CVE-2026-109618: interrupted initialisation

The first flaw is a control-flow management problem. When an out-of-memory condition triggers longjmp() while internal request data is only partially initialised, the cleanup path can treat invalid, uninitialised memory as though it were valid. The result is memory corruption. Because the attacker controls the trigger — an OOM condition is something you can provoke with a crafted request — Unit 42 describes the exploit as reliable, which is a word defenders should take seriously. Reliable RCE means the barrier between a curious researcher and a working exploit is low.

CVE-2026-109619: state that outlives its memory

The second flaw is subtler and, in some ways, more insidious. Here, request-owned internal state can survive after the memory backing it has been freed. PHP workers — the processes that handle requests, particularly under persistent models like PHP-FPM — then pick up the next request and may use that stale state before normal initialisation resets it. In effect, one request can leave a poisoned inheritance for the next one handled by the same worker. Those freed regions can later be read or branched on, and with sufficient control over heap layout, that becomes a path to arbitrary code execution.

CVERoot causeExploit path
CVE-2026-109618OOM handling via longjmp() leaves request memory uninitialisedAttacker-triggered OOM leads to corruption and RCE
CVE-2026-109619Fatal error handling leaves globals pointing at freed memoryStale state reused by a later request on the same worker

Both are unauthenticated. There is no login to bypass because there is nothing to log into — the attack surface is the request itself, before your application code has any say in the matter. That is what pushes the score to 9.2 and what makes the NCSC's language so direct.

The scale of exposure

Palo Alto Networks' Cortex Xpanse telemetry identified over 22.6 million exposed instances potentially vulnerable to these CVEs. That figure counts internet-facing services where the fingerprint suggests a vulnerable PHP runtime, and it is almost certainly an undercount once you factor in appliances, embedded management interfaces, and internal systems that are reachable from a compromised workstation. Unit 42 also reports that at least one European government took its website offline as a precaution — a decision that tells you something about how seriously the proof of concept was taken by people who had seen it.

For a defender, the uncomfortable question is not "do we run PHP?" but "where don't we know we run PHP?" Content management systems, ticketing platforms, CRM front-ends, monitoring dashboards, network appliances with web UIs, build servers, and container base images all routinely ship with a PHP interpreter underneath. The NCSC-NL inventory of software products with a PHP dependency is a useful starting point precisely because it captures that second-order exposure.

Caution: A common mistake in the first 48 hours of a vulnerability like this is to scan only for the version string reported by package managers. Appliances and bundled stacks frequently ship patched or customised PHP builds that do not advertise their true patch level. Treat version detection as a hint, not a verdict.

What to do, in priority order

The NCSC's priority actions are worth following closely, because they are sequenced sensibly for an incident of this shape.

  • Discover PHP everywhere, internet-facing first. Do not filter by version. Enumerate interpreter installations across servers, containers, and appliances, then rank by external reachability.
  • Patch to the latest fixed PHP release. The PHP project has published the security update; apply it and continue to track future releases. If you are on an end-of-life branch, move to a fully supported version rather than backporting.
  • Watch third-party vendors. Appliances and services that bundle PHP need their own updates. Monitor vendor advisories continuously, not once.
  • Apply the PHP Team's hardening guidance in addition to the patch — defence in depth against the next interpreter flaw.
  • If you cannot patch immediately, apply the temporary mitigations published by the PHP Team. If those are impractical or too slow, take the system offline.
  • If you cannot update or disable a system, assess it for evidence of compromise and for attacker-installed backdoors before you upgrade. Patching over an intrusion does not remove the intruder.

That last point deserves emphasis. These are unauthenticated RCE flaws with public proof of concept. The window between disclosure and exploitation is measured in hours, not weeks, and a compromised PHP worker is an excellent place to hide — the attacker inherits the web server's privileges, its database credentials, and its outbound network position. If a system was exposed and unpatched for any meaningful period, assume compromise until you can show otherwise, and bring in an NCSC-assured incident response provider if you lack the in-house capability to do that forensically.

Detection and verification

From a pentesting perspective, the practical challenge with interpreter-level bugs is that they leave few fingerprints in application logs. The request that triggers an OOM does not look like an attack to your WAF — it looks like a large upload, a pathological regex, a deeply nested JSON body, or a request that simply asks for too much. The exploitation happens below the layer your application logging sees.

That means detection has to lean on infrastructure signals: unexpected worker crashes and restarts, anomalous memory pressure on PHP-FPM pools, core dumps appearing where they should not, and outbound connections from web servers to unfamiliar destinations. On the prevention side, virtual patching through network security controls can buy time — Palo Alto's Advanced Threat Prevention Plus with Frontier Virtual Patching has covered these CVEs via signature 543004 since 20 October 2026 — but virtual patching is a bridge, not a destination. The interpreter still needs the real fix.

If you want to validate your own exposure before an attacker does, the honest approach is to test the runtime directly: confirm the patch level of every interpreter you find, exercise the OOM and fatal-error paths in a controlled environment, and verify that worker state does not leak between requests. That is precisely the kind of runtime-level assessment that application-layer scanning tends to miss, and it is where a focused penetration test earns its keep on a vulnerability of this class.

The bigger lesson

What makes CVE-2026-109618 and CVE-2026-109619 notable is not that PHP had a memory-safety bug — every large C codebase eventually does. It is the reminder that the interpreter is part of your attack surface, and it is the part most organisations inventory least carefully. We tend to know our applications intimately and our runtimes barely at all. When a flaw lands in the runtime, that asymmetry becomes the vulnerability.

The organisations that come through this cleanly will be the ones that already had a reliable answer to "where is PHP running, and at what version?" — and that treated the answer as a living inventory rather than a one-off spreadsheet. If you did not have that answer on 21 October, building it now is the most valuable thing you can do this week, ahead of the next interpreter flaw that will inevitably follow.

All articles