[PHP-DEV] From mono-implementation risk to spec: Lessons from CVE-2026-109618/109619 and a path to K/Redex semantics[Idea]

Hi internals,

I want to raise a broader process question following the
emergency releases on Oct 21 for CVE-2026-109618 and
CVE-2026-109619.

I had noted privately back in 2020 that given the lack of a
formal spec and single-implementation status, I expected the
next critical vulnerability to be in the language runtime and
execution layer itself — not in ext/dom, ext/curl, ext/gd,
or HTTP handling — but in memory allocation and hashtable
management. The October disclosures matched that pattern,
which is why I’m writing now.

What happened:

  • CVE-2026-109618 (CVSS 9.2, “rawkey”): in Zend Engine’s
    HashTable implementation, _zend_hash_str_add_or_update_i
    increments the entry count before allocating the new
    key. If that allocation exceeds memory_limit, Zend calls
    zend_bailout() via longjmp, abandoning the request with a
    counted-but-uninitialized bucket. Request shutdown then
    treats stale memory as a valid zend_string. Requires a
    POST with a large field name (>1MB).

  • CVE-2026-109619 (CVSS 9.2, “stale global state”): in
    session.upload_progress, request-owned state is retained
    after free and reused by a later request on the same
    worker. Small body (~450 bytes).

Fixed in 8.2.35, 8.3.36, 8.4.27, 8.5.12. The advisories note
the underlying code goes back to PHP 5.4. Exploitation is
below the application layer — mod_php was confirmed
exploitable before any application code runs.

This is not a bug in an extension. It is a bug in ZendMM,
zend_hash, and request lifecycle — the core runtime.

Why this matters beyond the patch:

PHP today has no formal specification. As the KPHP work
(Filaretti et al., ECOOP’14) notes, Zend is the de-facto
spec. That makes this class of bug hard to catch:

  1. No alternative implementation to disagree with Zend.
    Python has CPython/PyPy/Cython, JavaScript has
    V8/SpiderMonkey/JSC, .NET has CoreCLR/Mono. PHP had
    HHVM and has PeachPie (.NET), but without a stable
    bytecode/parser spec, compatibility diverged — HHVM
    dropped PHP compat in 2019 to become Hack, PeachPie
    needs workarounds for Laravel. We are back to one
    reference implementation.

  2. No stable bytecode spec for independent tooling. The
    vulnerable pattern — count-before-alloc + OOM bailout —
    could have been modeled and fuzzed if the invariants of
    HashTable and ZendMM were specified outside of C.

The broader ecosystem point:

.NET is a useful counter-example, not because “Microsoft
exists”, but because it chose to keep alternative runtimes.
.NET Framework was proprietary and Windows-only. Mono (2001)
was the independent implementation that pushed it open.
Microsoft open-sourced .NET Core in 2014, it became truly
cross-platform (ASP.NET Core on Linux/macOS/Windows), and
today .NET intentionally ships both CoreCLR and Mono runtimes
to stress-test feature additions. The .NET Foundation model
is similar to what the PHP Foundation has been building
since 2021.

PHP’s trajectory was the opposite: we lost the second
implementation. The cost is not that PHP becomes “irrelevant”
overnight — it powers a huge share of the web — but that
trust erosion makes teams choose Node/Python/Go for new
systems while keeping PHP for existing WordPress installs.
Long-lived runtime RCEs accelerate that.

Why I think a spec effort is more tractable now:

The CVE-2026-109618 lead was flagged by automated audit
tooling (Ryan Austin’s agent flagged the count-before-alloc
in _zend_hash_str_add_or_update_i). AI-assisted auditing of
the Zend heap path is now practical.

Similarly, recent AI-assisted re-implementations of legacy
binary formats and apps from scratch (e.g., ArtCraft’s work
cloning apps and data formats in Rust with no legacy code)
show that re-implementing a complex legacy format from a
reference implementation + test suite is more feasible today
than when KPHP was manually written in 2014.

We can leverage that to bootstrap PHP semantics.

Proposal for discussion, not an embargo:

I am not proposing freezing features or cosmetic deprecations.
I am proposing we use this incident to start:

A) Formalize Zend bytecode and parser as a living spec
extracted from php-src (8.4/8.5 baseline), including
OOM/bailout semantics.

B) Reference executable semantics in two formal frameworks:

  • K Framework (building on KPHP)
  • PLT Redex / Racket, to cross-check the model
    Both should model HashTable invariants, ZendMM alloc
    failure, and request lifecycle.

C) PyPy/Roslyn-style bootstrapping: a compiler from PHP to
Zend bytecode and to other targets (e.g., JS) to validate
semantics, plus self-hosting tests (compile the bootstrap
compiler with itself).

D) Conformance via differential testing: run phpt plus
WordPress, MediaWiki, Laravel, Symfony against any
alternative runtime, not just phpt.

If there is interest, I can draft a short RFC outline for
(A) + (B) as a first step, and talk to the PHP Foundation
(contact@thephp.foundation) about whether this is fundable
as Foundation work.

Thanks for reading this long mail,

Brian

Hi Brian,

On 24 October 2026 21:59:35 BST, Brian Nguyen <musicdenotation@gmail.com> wrote:

The vulnerable pattern — count-before-alloc + OOM bailout —
  could have been modeled and fuzzed if the invariants of
  HashTable and ZendMM were specified outside of C.

It seems to be that the memory manager and internal structures are exactly the part that would vary between implementations. PHPNG (the basis of 7.0) heavily rewrote exactly those parts; an implementation on top of another runtime like .net or JVM would naturally make use of their underlying memory management; a rewrite in fully-checked Rust or Zig would use different mechanisms than one in C. A meaningful spec would cover all of those, asserting that the behaviour observed from the outside matches.

I can't see how a specification would have helped here, any more than the HTML Specification helps prevent memory management bugs in browser implementations.

.NET is a useful counter-example, not because "Microsoft
exists", but because it chose to keep alternative runtimes.

Microsoft employs about 200_000 people. If 0.01% of those are paid to work full time on .NET, that's still twice as many as have ever been paid to work full time on PHP.

If someone came along offering to create a competing implementation of PHP, I would beg them to instead spend the effort improving the one we already have.

Regards,

Rowan Tommins
[IMSoP]

On Sat, Oct 24, 2026, at 22:59, Brian Nguyen wrote:

PHP today has no formal specification. As the KPHP work
(Filaretti et al., ECOOP’14) notes, Zend is the de-facto
spec. That makes this class of bug hard to catch:
…
I am proposing we use this incident to start:

A) Formalize Zend bytecode and parser as a living spec
B) Reference executable semantics in two formal frameworks:

I think PHP is not starved for bugs. The bottleneck is bugfixes. As I understand it the problems leading to these CVEs were already found by an earlier security test, but the problem was coming up with a good fix. I think creating a spec and a second implementation is not the most efficient way to find and solve bugs.

Regards,

Sjoerd Langkemper

On Sun, Oct 25, 2026, at 10:32 AM, Sjoerd Langkemper wrote:

On Sat, Oct 24, 2026, at 22:59, Brian Nguyen wrote:

PHP today has no formal specification. As the KPHP work
(Filaretti et al., ECOOP'14) notes, Zend is the de-facto
spec. That makes this class of bug hard to catch:
...
I am proposing we use this incident to start:

A) Formalize Zend bytecode and parser as a living spec
B) Reference executable semantics in two formal frameworks:

I think PHP is not starved for bugs. The bottleneck is bugfixes. As I
understand it the problems leading to these CVEs were already found by
an earlier security test, but the problem was coming up with a good
fix. I think creating a spec and a second implementation is not the
most efficient way to find and solve bugs.

Regards,

Sjoerd Langkemper

To be blunt, the way to address the bottlenecks on bug fixing is to badger PHP-using companies into becoming significant PHP Foundation sponsors. Or dedicating their own employees full time to PHP maintenance.

This is a money problem, just like most major OSS projects. It's nothing more complicated than that. A formal spec may have merit, but it has no relevance to the current situation.

--Larry Garfield