The PHP team shipped PHP 8.5.8 on July 2, 2026, and it carries one CVE plus a fix for a SOAP regression that showed up in the 8.5 series. The security fix is a heap corruption in openssl_encrypt() when you use the AES-WRAP-PAD cipher, and it's patched across 8.2.32, 8.3.32, 8.4.23, and 8.5.8.
Here's what's in it:
- Memory corruption in
openssl_encrypt()with AES-WRAP-PAD (CVE-2026-14355) SoapServer::handle()works again without passing the raw request body- Three Opcache fixes, including a production segfault tied to the inheritance cache and reentrant autoloading
- A bypass of Phar's magic
.phardirectory protection inPhar::addEmptyDir() - Memory leak fixes in Zip and Zlib, plus corrections in Date, Exif, Intl, Reflection, and SQLite
Security Fix
Memory Corruption in openssl_encrypt() with AES-WRAP-PAD
RFC 5649 key wrapping with padding expands the plaintext to the next 8 byte boundary and then prepends an 8 byte header, so the output is always longer than what you put in. PHP sized its buffer from the input length alone, which left OpenSSL writing past the end of the allocation and corrupting heap metadata. What you get is an abort with zend_mm_heap corrupted, so the practical risk is a crash rather than data exposure.
AES-WRAP-PAD isn't a cipher many applications reach for, which is part of why it's rated moderate at CVSS 4.8. If you do wrap keys with it, this is the release you want. Fixed by David Carlier.
Advisory: GHSA-7jrw-539f-x6vr Issue: GH-22187
What Else Is Fixed
SoapServer::handle() Without the Raw Body
In the 8.5 series, calling handle() with no arguments stopped processing the incoming request correctly, and the server would pick the first method in the WSDL instead of the one that was actually called. The workaround was to read the body yourself:
$server->handle(file_get_contents('php://input'));
8.5.8 restores the no-argument behavior, so $server->handle() reads the request the way it did on 8.4. The same release fixes a crash in handle() when $_SERVER isn't an array, which happens if something in your bootstrap replaces it. Both fixes came from David Carlier and Niels Dossche.
Three Opcache Fixes
GH-20469 is the one to read if you run PHP-FPM in production. The inheritance cache could replay an entry unsafely when autoloading was reentrant, one autoloader triggering another, and the bad class entry then crashed inside instanceof_function_slow(). Reporters saw it as a bare segfault in the kernel log with no PHP-level stack to work from.
GH-21972 produces an error message you have to read twice:
TypeError: strtolower(): Argument #1 ($string) must be of type string, string given
A typed by-value return carrying a reference wrapper corrupted the variable's type information, so a value that printed fine came back from gettype() as unknown type. Fixed by Weilin Du.
GH-22265 is the second tailcall VM interrupt crash in two releases, after the one that went out in 8.5.7. Levi Morrison found and fixed both.
Phar Directory Protection
Phar treats .phar as a reserved directory name, and Phar::addEmptyDir() wasn't applying that check to paths starting with /.phar. The fix closes that path while still allowing directory names that merely share the .phar prefix without being the magic one. Phar also picked up a fix for an integer underflow when parsing ZIP extra fields. Both from Weilin Du.
Other Fixes Worth Noting
Niels Dossche cleared out several memory leaks: error paths in Zip, a deflate initialization failure that leaked when a dictionary was set, and one in inflate_add(). He also corrected the recurrence check in DatePeriod::createFromISO8601String(), Exif reads for single and double tags, and error checks on SQLite column retrieval.
Core got two fixes: an incorrect compile error for a goto targeting a label that precedes a try/finally block (GH-22280, Pratik Bhujel) and an assertion when an error handler throws during NaN coercion to bool or string (GH-22112).
The URI extension that arrived in PHP 8.5 now clears its error log before each Uri\WhatWg\Url wither call, so a UrlValidationError no longer reports errors left over from an earlier call. Windows static builds also got LEXBOR_STATIC added to the URI CFLAGS so ext/uri doesn't treat LXB_API as an import. Reflection preserves class-name case in ReflectionClass::getProperty() error messages and during autoloading, and Intl corrected the argument positions reported by transliterator_transliterate() along with the error state on IntlTimeZone::getDisplayName(). BCMath rounded out the list with fixes for oversized allocations and signed overflow in bcround() and BcMath\Number::round().
Upgrade Notes
No breaking changes and no new features, this is a patch release. If you call openssl_encrypt() with AES-WRAP-PAD, or you've been passing the raw request body to SoapServer::handle() as a workaround, take this one now. Everything else here is comfortable in a normal maintenance window. The OpenSSL CVE is also patched in 8.4.23, 8.3.32, and 8.2.32.
Most readers will pick this up through a distribution package or a Docker image rather than building from source.