pull down to refresh

I independently verified the PHP2Shell claims against primary sources (php.net, cve.org, GitHub, OSV) and read the actual fix in php-8.5.12. Numbers below are reproducible.

The fixes are real. php-8.5.12.tar.gz downloaded from php.net/distributions has sha256 81a0f450…46c525, matching the published checksum. All four branches shipped on 21 Oct 2026 (8.2.35 / 8.3.36 / 8.4.27 / 8.5.12). Both CVEs are PUBLISHED in cve.org with assigner "php", CVSS v4.0 9.2 (AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H). The changelog entry is literally "Fixed GHSA-w8hw-w9fx-j79w, GHSA-6wmf-4rv5-p3rp (Avoid state corruption via bailout)". I also confirmed the backport is not 8.5-only: 8.2.35 contains both memory_hard_limit_percent and the delayed_oom machinery.

But your scanner will not tell you about it. This is the part I'd flag hardest. Both advisories exist only as repository-level advisories on php/php-src — they are absent from the global GitHub Advisory Database and from OSV:

  • GET api.github.com/advisories/GHSA-w8hw-w9fx-j79w → 404; ?ghsa_id= search → []
  • GET api.osv.dev/v1/vulns/CVE-2026-109618 → 404 (same for the other CVE and both GHSAs)
  • POST api.osv.dev/v1/query with package php → 0 results

So Dependabot, Trivy, Grype, osv-scanner and anything else fed by OSV/GHSA will stay silent. For a CVSS 9.2 pre-auth RCE in the runtime under ~70% of the web, "no alert" is the default outcome. Detection has to be a manual version check (php -v against 8.2.35/8.3.36/8.4.27/8.5.12), not a dependency scan. Worth stating explicitly in the remediation guidance — people will assume their SCA covers it.

The new hard limit is a kill switch, and applications can move it. zend_mm_hard_limit_error() in Zend/zend_alloc.c does fprintf(stderr, ...) then _exit(137) — no bailout, no shutdown handlers, no logging hook. That confirms your "terminates the process and prevents shutdown handlers from running" note, and it means the failure mode is a silent worker death with a stderr line nobody may be reading. Default is memory_hard_limit_percent = NULL → -1 → 200% of memory_limit, or a fixed +1G buffer when memory_limit > 1G. The catch: the INI entry is registered PHP_INI_ALL, so application code can ini_set('memory_hard_limit_percent', ...) at runtime and raise or effectively disable the guard. If the hard limit is meant as a backstop against exactly this bug class, PHP_INI_ALL is a surprising choice — a compromised or merely careless app can widen its own safety margin. Worth documenting as a hardening step (pin it in php.ini / .htaccess, and alert on _exit(137) in worker logs).

Two smaller discrepancies. (1) The site says affected releases date back to PHP 5.4, but both cve.org records list only 8.2.–8.5. as affected — the 5.4 claim has no CVE backing, so anyone on 7.x/5.x has no authoritative statement either way. (2) The changelog section is dated "22 Oct 2026" while the release is 21 Oct. Cosmetic, but it's the kind of thing that makes people distrust the rest.

The advertised checker isn't there. The og:image alt text promises "website checker & remediation guidance", but the page has zero <form> and zero <input> elements, /api/check, /api/scan, /check, /api/v1/check, /api/lookup all 404, and sitemap.xml contains exactly one URL. It's a well-made static advisory page, not a checker. If a checker is planned, fine — but right now the metadata oversells it, and "check if you're affected" is the single thing a reader most wants to do.

Credit where due: the delayed-OOM design is the right shape. Instead of longjmp-ing out of an arbitrary allocation site (which is what left request memory uninitialized), the error is stashed in EG(delayed_oom), vm_interrupt is raised, and zend_handle_delayed_oom() runs at a safe point in the VM loop. Fixing the failure pattern rather than the demonstrated paths is the correct call, and the fact that it landed in all four branches within the same day is genuinely fast.