Visit NES for PHP Home Page
NES for PHP 8 Release Notes: PHP 8.0
Comprehensive release notes and changelog for NES for PHP 8 Release Notes: PHP 8.0, including security patches, bug fixes, and feature updates across all supported versions.
57 Patched Vulnerabilities
VEX Statements
PHP 8.0
8.0.1 (NES) - October 30, 2026
Packages: https://registry.nes.herodevs.com/bin/nes/php/v8.0.30-nes-8.0.1/ (Ubuntu 22.04, amd64; see Installation)
Package versions: 1:8.0.30+nes8.0.1-1~ubuntu22.04 (php-common: 2:101.nes8.0.1~ubuntu22.04)
Based on PHP 8.0.30.
This release patches the following CVEs:
- CVE-2024-2756 Incomplete CVE-2022-31629 fix: cookie names with an unmatched
[, such as.[Host-testor_[Secure-test, were mangled into__Host-test/__Secure-testafter the check that rejects them, so a network or same-site attacker could set an ordinary cookie that the application takes for a__Host-or__Secure-cookie. - (Medium) - CVE-2024-3096 A bcrypt password starting with a NUL byte was hashed as the empty string, so
password_verify()accepted an empty password for that hash (the fix commit names the draft id GHSA-q6x7-frmf-grcw). - (Medium) - CVE-2024-5458
FILTER_VALIDATE_URLreturned success as soon as the host was a bracketed IPv6 address and skipped the userinfo check, so URLs with invalid userinfo were accepted and could be parsed differently later. - (Medium) - CVE-2024-8925 A multipart boundary longer than the read buffer was not recognised when it was split across reads, so part of a body could be merged into another field or dropped, letting an attacker who controls part of the data hide other fields. - (Low)
- CVE-2024-8927
cgi.force_redirectacceptedHTTP_REDIRECT_STATUS, which a client sets with aRedirect-Status:request header, so a request straight to php-cgi passed the check; in some configurations this allows arbitrary file inclusion. - (High) - CVE-2024-11234 With an HTTP proxy in the stream context and
request_fulluri, a request URI containing CR/LF from user input could add headers or whole requests sent through the proxy (request smuggling, requests to resources the proxy can reach). - (Medium) - CVE-2024-8932 On 32-bit systems the length of the escaped string could overflow for an input of about 1.4 GB, so
ldap_escape()wrote past its buffer. - (Critical) - CVE-2024-11233 A chunk ending in
=\rmade theconvert.quoted-printable-decodefilter read one byte past its input buffer, which can crash or disclose a byte of memory. - (Medium) - GHSA-4w77-75f9-2c8w Heap use-after-free: in the CLI built-in web server, a request without
Content-Typekept the previous request's content type pointer, freed with that request, andsapi_read_post_data()read it. - (Low) - CVE-2025-14177 getimagesize read JPEG APPn segments that span several reads into a buffer it had not filled completely, so uninitialised heap memory could be returned to the script in the APP data (information leak). - (Medium)
- CVE-2025-14178
array_merge()summed the sizes of its arguments in 32 bits and sized the result array from the sum, so a very large merge overflowed the allocation and wrote past the end of the heap block. - (Medium) - GHSA-www2-q4fc-65wf
gethostbyname(),gethostbynamel(),gethostbyaddr(),dns_get_record(),checkdnsrr(),getmxrr(),getservbyname(),getprotobyname(),inet_pton()andip2long()took the part of their argument before a NUL byte, so a name with a NUL byte resolved as a shorter one. - CVE-2026-7259 mb_ereg_search_init with an invalid encoding left the search state so that php_mb_check_encoding dereferenced a NULL pointer: a crash (denial of service). - (Low)
- CVE-2026-7568
metaphone()indexed its input with a signedintoffset while the string length is asize_t, so a very long string overflowed the signed integer and read out of bounds. - (Medium) - CVE-2026-92842 The
convert.base64-encodeandconvert.quoted-printable-*filters copied aline-break-charsoption withpestrdup(), which stops at a NUL, but kept its full length, so the filter read past its copy and put heap bytes into its output (information disclosure). - (Medium) - GHSA-ch8v-r6jh-4vvr
php_filter_encode_url()initialised 255 of the 256 entries of its "must encode" table, so whether byte 0xFF was percent-encoded byFILTER_SANITIZE_ENCODEDdepended on stack contents. - (Low) - CVE-2026-14355
openssl_encrypt()sized its output buffer for a block cipher, too small for the AES key wrap with padding modes (AES-*-WRAP-PAD), so a call wrote past the end of the heap block. - (Medium) - CVE-2026-91769 Peer verification fell back to the certificate's Common Name whenever no subjectAltName matched, so a certificate whose SAN names another host but whose CN holds the expected name was accepted (RFC 6125 forbids the fallback once a DNS, SRV or URI identity is present). - (Medium)
- CVE-2026-91767
php_openssl_matches_wildcard_name()checked only the suffix's length, so a certificate wildcard name whose literal parts together were longer than the peer name made the length passed tomemchr()wrap and read far past the name (heap out-of-bounds read). - (Medium) - CVE-2025-1217 The HTTP stream wrapper (
fopen(),file_get_contents()onhttp://) mis-parsed a response header folded onto a continuation line, so a malicious server could make the client take part of a header as another. - (Medium) - CVE-2025-1734 The HTTP stream wrapper accepted response header lines without a colon (and lines with other malformed shapes) as headers, so a malicious server could smuggle a header past the wrapper's checks. - (Medium)
- CVE-2025-1861 The HTTP stream wrapper kept a redirect's
Locationheader in a buffer of 1024 bytes and truncated a longer one, so a malicious server could make the client follow a different URL than the one it sent. - (Medium) - CVE-2025-1736
check_has_header()decided whether theheaderstream context option already holds a standard header (Authorization,Host,User-Agent...) and accepted a match that followed a bare LF, although requests separate headers with CRLF. - (Medium) - CVE-2026-91766 The HTTP stream wrapper kept the
Authorizationheader (and credentials in the URL, a cookie) when it followed a redirect to another origin, handing them to a server the script never meant to trust. - (Medium) - CVE-2026-93682 The HTTP stream wrapper read before the start of a redirect's
Locationheader value when that value was empty, an over-read of the response buffer. - (Medium) - CVE-2025-1220
fsockopen(),stream_socket_client()and the stream transports took the part of a host name before a NUL byte as the host and the rest as ignored, so a name such aslocalhost\0.example.comconnected to localhost after a check against the longer name. - (Low) - CVE-2025-6491 SOAP gave libxml2 an over-long XML name for a
SoapVarorSoapParamnode (a very large namespace prefix or element name); libxml2 then did not set the node's name and the encoder compared a NULL name withstrcmp()inserialize_zval()(a SoapClient serialising theSoapVar), a NULL pointer dereference; the server-sideserialize_response_call2()has the same comparison. - (Medium) - CVE-2026-6722 The SOAP
apache:Mapdecoder stored values in its reference map (SOAP_GLOBAL(ref_map)) without holding a reference to them, so a later lookup in the same message used a value freed in between (use-after-free). - (Critical) - CVE-2026-7261
SoapServer::handle()freed the session-persisted server object when a SOAP header raised a fault or an exception withSOAP_PERSISTENCE_SESSIONon, while the session still held it, and a later request used the freed object (use-after-free). - (Medium) - CVE-2026-7262 The SOAP
apache:Mapdecoder checked the wrong node for NULL, so a map item with a missing<value>element dereferenced a NULL pointer and crashed the process. - (Low) - CVE-2026-91765 The SOAP XML parsing and decoding code (
cleanup_xml_node(),master_to_zval_int()) recursed with the nesting depth of the document, or of itshrefreferences, so a deeply nested message overflowed the stack and crashed the process. - (High) - CVE-2025-14181
get_http_body()ofSoapClientkept the body size of a chunked HTTP response in anintand checked the sum of two chunk sizes for overflow with signed arithmetic, which the compiler may remove: a malicious SOAP server could make the client reallocate a buffer too small for the data it then read into it (heap buffer overflow). - (Medium) - CVE-2024-9026 php-fpm's handling of log lines from its children (catch_workers_output) could be made to drop or alter up to four characters at the start or end of a log message, so a worker's output could spoof or hide log content. - (Low)
- CVE-2026-6735 The full PHP-FPM status page (
?full&html,?full&xml) printed each worker's request URI unescaped in its HTML and XML output, and escaped the query string without quote flags, so a crafted request gave cross-site scripting against whoever opens the status page. - (High) - CVE-2026-91768 The FastCGI client check compared IPv6 addresses on 12 of 16 bytes, so an allowed address matched a whole /96 prefix and other hosts in it could talk FastCGI to the pool (run scripts with arbitrary parameters). - (Medium)
- CVE-2026-7260
phar_get_link_source()followed the symbolic links of a tar archive recursively without a bound, so a phar with circular symlinks overflowed the stack and crashed the process. - (Medium) - CVE-2026-6103
phar_parse_tarfile()read a tar entry's octal size into 32 bits without checking it, and skipped the data blocks of regular files only, so an oversized size or the data of another entry type was then parsed as further tar headers: a crafted archive could make PHP see entries that other tools do not (archive entry injection, e.g. past a scanner). - (Medium) - CVE-2025-1219 When libxml-based extensions loaded a document over HTTP and the server redirected, PHP passed the content-type of the first response, not the final one, to the charset detection, so a document could be parsed with the wrong character set. - (Medium)
- GHSA-wg4p-4hqh-c3g9 With
XML_OPTION_SKIP_TAGSTARTset,xml_parse_into_struct()passedtag_name + skipto the info table before checking that the tag name was longer than the skip, an out-of-bounds read of the tag name. - CVE-2024-8929 mysqlnd trusted lengths in packets from the MySQL server: a malicious server could make the client read past a packet (the OK packet, the result set header, field metadata, LOCAL INFILE and authentication plugin messages, binary and text rows) and return the heap bytes it read to the script. - (Medium)
- CVE-2025-1218 mysqlnd read several fields of server packets (OK, EOF, error, result set field, row, prepare response) without checking that the packet holds them, so a hostile or compromised MySQL server, or a man in the middle on an unencrypted connection, could make PHP read past the packet buffer and leak heap memory or crash. - (Low)
- CVE-2024-11236 On 32-bit systems the quoted length of a very long string overflowed in the dblib and Firebird quoters, so
PDO::quote()wrote past its buffer. - (Critical) - CVE-2025-1735
pg_escape_string(),pg_insert(),pg_update(),pg_convert()and the PDO_PgSQL quoter ignored the error PQescapeStringConn reports (for example for bytes invalid in the connection's encoding) and used the half-escaped string in a query, which can leave a value or name improperly escaped. - (Medium) - CVE-2025-14179 PDO:quote on a pdo_firebird connection stopped doubling quotes at the first NUL byte, so the rest of the string was copied into the SQL text unescaped: SQL injection. - (High)
- CVE-2026-17543
pg_convert(), and through itpg_insert(),pg_update(),pg_select()andpg_delete(), quoted escaped strings asE'...'; withstandard_conforming_stringson (PostgreSQL's default)PQescapeStringConn()leaves backslashes alone, so a value such asx\' OR 1=1 --closed the literal (SQL injection through values a script believes are escaped). - (High) - CVE-2026-7258 Many functions (
urldecode()among them) passed a signedcharto the ctype.h functions; for bytes >= 0x80 the argument was negative, and C libraries whose tables do not cover negative values read out of bounds. - (Medium) - CVE-2026-9672 The GIF LZW decoder of the bundled libgd (
LWZReadByte_(),ReadImage()) read uninitialised stack memory and went out of bounds on a crafted GIF with a repeated clear code. - CVE-2021-38115 The bundled libgd's TGA reader ignored a short read of the image identification field, leaving the buffer uninitialised (CVE-2021-38115), and its BMP and WebP writers ignored gdPutBuf results, the BMP writer's error path freeing the caller's context (CVE-2021-40812).
- CVE-2022-1586 The bundled PCRE2 10.35 of PHP 8.0.30 misses later JIT fixes: CVE-2022-1586 (out-of-bounds read in compile_xclass_matchingpath for Unicode property classes, fixed in 10.40), CVE-2022-1587 (out-of-bounds read in get_recurse_data_length for recursions, 10.40) and CVE-2026-89156 (pcre2_match runs the JIT without validating the whole UTF subject, 10.48).
- CVE-2026-103111 A PCRE2 JIT stack allocation larger than the growth step wrote below the stack (CVE-2026-103111, advisory GHSA-r9hj-j2rw-4q3m, fixed in PCRE2 10.49). ext/pcre creates a growable JIT stack, so the code is reachable. - (High)
- CVE-2024-2408 The Marvin attack: RSA decryption with PKCS#1 v1.5 padding leaks through timing whether the padding was valid, so an attacker who can submit many ciphertexts and time the answers can decrypt a ciphertext or forge a signature. - (Medium)
Upgrade notes
- This is the first release of NES for PHP 8.0. It is for Ubuntu 22.04 on amd64 (x86_64) only. There are no RPMs, no container images and no Windows zip for PHP 8.0.
- The release is one signed apt repository in one archive,
php-v8.0.30-nes-8.0.1.ubuntu2204.amd64.repo.tar.xz. It holds the release signing key and arepo/directory with the 39 packages and their signed index. Download it with the key and the checksums, then verify them:base=https://registry.nes.herodevs.com/bin/nes/php/v8.0.30-nes-8.0.1 auth="<your-contact-email>:<your-nes-access-token>" for f in RPM-GPG-KEY-php-nes SHASUMS256.txt SHASUMS256.txt.asc php-v8.0.30-nes-8.0.1.ubuntu2204.amd64.repo.tar.xz; do curl -fSLO -u "$auth" "$base/$f" done gpg --show-keys RPM-GPG-KEY-php-nes # must show CA44E935A3995EB733AF292B18DD1E9212F3C6A2 gpg --import RPM-GPG-KEY-php-nes gpg --verify SHASUMS256.txt.asc SHASUMS256.txt sha256sum -c --ignore-missing SHASUMS256.txt - To install on a host without PHP 8.0, extract the archive to
/opt/nes-phpand add it as an apt source. apt reads an armored key only when its file name ends in.asc, so the key goes to/usr/share/keyrings/nes-php.asc. Then installphp-commonand the packages you need:sudo mkdir -p /opt/nes-php sudo tar -xJf php-v8.0.30-nes-8.0.1.ubuntu2204.amd64.repo.tar.xz -C /opt/nes-php --strip-components=1 sudo cp /opt/nes-php/RPM-GPG-KEY-php-nes /usr/share/keyrings/nes-php.asc echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/nes-php.asc] file:/opt/nes-php/repo ./' | sudo tee /etc/apt/sources.list.d/nes-php.list sudo apt-get update sudo apt-get install --no-remove --no-install-recommends php-common php8.0-cli php8.0-fpm php8.0 -v - The 39 packages are
php-common,php8.0,php8.0-common,php8.0-cli,php8.0-fpm,php8.0-cgi,php8.0-phpdbg,libapache2-mod-php8.0,libphp8.0-embed,php8.0-devand 27 extension packages:php8.0-bcmath,php8.0-bz2,php8.0-curl,php8.0-dba,php8.0-enchant,php8.0-gd,php8.0-gmp,php8.0-imap,php8.0-interbase,php8.0-intl,php8.0-ldap,php8.0-litespeed,php8.0-mbstring,php8.0-mysql,php8.0-odbc,php8.0-opcache,php8.0-pgsql,php8.0-pspell,php8.0-readline,php8.0-snmp,php8.0-soap,php8.0-sqlite3,php8.0-sybase,php8.0-tidy,php8.0-xml,php8.0-xslandphp8.0-zip, and the GD library packageslibgd3andlibgd-dev. They keep the usual Ubuntu paths:/usr/bin/php8.0,/etc/php/8.0/<sapi>/php.iniand/usr/lib/php/20200930/for extensions. Turn an extension on or off withphpenmod -v 8.0andphpdismod -v 8.0. libgd3andlibgd-devare version2.3.0-2ubuntu2.3+nes1: Ubuntu's libgd 2.3.0 with a GIF decoder fix.php8.0-gdneeds exactly this version, so apt installs it withphp8.0-gdin place of Ubuntu'slibgd3. The library ABI and soname (libgd.so.3) are Ubuntu's, so other programs on the host that use libgd keep working. A PHP rollback keeps thislibgd3.- Apache runs PHP through
libapache2-mod-php8.0with the prefork MPM:sudo a2dismod mpm_event sudo a2enmod mpm_prefork php8.0 sudo apache2ctl -t sudo service apache2 restart - php-fpm is the
php8.0-fpmservice (sudo service php8.0-fpm start). It listens on/run/php/php8.0-fpm.sock, owned bywww-data. - Other PHP versions on the host, such as Ubuntu's own PHP 8.1, keep
working, and the
phpcommand keeps pointing where it did. Runphp8.0, or pointphpat it withsudo update-alternatives --set php /usr/bin/php8.0. - Ubuntu 22.04 has no PHP 8.0 of its own. A host that has PHP 8.0.30
packages from another repository can upgrade to these. The NES versions
sort above the other builds of 8.0.30: every package is
1:8.0.30+nes8.0.1-1~ubuntu22.04, andphp-commonis2:101.nes8.0.1~ubuntu22.04. The tested upgrade replaces the 36 versioned PHP 8.0 packages in one apt command and keeps the host'sphp-common. First keep the packages you have, so you can roll back. Their versions must still be in their repository:mkdir -p ~/php-8.0-rollback && cd ~/php-8.0-rollback apt-get download $(dpkg-query -W -f '${db:Status-Abbrev} ${Package}=${Version}\n' | awk '$1 ~ /^i/ && $2 ~ /^(php8\.0|libapache2-mod-php8\.0|libphp8\.0-embed)/ { print $2 }')
Then add the NES repository as above, without the install line, and upgrade:sudo apt-get install --no-remove --no-install-recommends $(dpkg-query -W -f '${db:Status-Abbrev} ${Package}\n' | awk '$1 ~ /^i/ && $2 ~ /^(php8\.0|libapache2-mod-php8\.0|libphp8\.0-embed)/ { print $2 }') sudo service php8.0-fpm restart sudo service apache2 restart
With--no-remove, apt stops instead of removing a package. Extension packages from the other repository that NES does not ship are not part of the tested upgrade: remove them first, and build the extension againstphp8.0-devinstead (see below). - To roll back, install the packages you kept. Only this step allows apt to
downgrade. Then take the NES source out, so that apt does not upgrade
again:
cd ~/php-8.0-rollback sudo apt-get install --allow-downgrades --no-remove --no-install-recommends ./*.deb sudo rm /etc/apt/sources.list.d/nes-php.list sudo apt-get update sudo service php8.0-fpm restart sudo service apache2 restart
The upgrade and the rollback keep your edits to/etc/php/8.0/cli/php.ini, and the extensions you turned off stay off. php8.0 -vandPHP_VERSIONreport8.0.30-nes, soversion_compare(PHP_VERSION, '8.0.30', '>=')is false.PHP_VERSION_IDstays 80030.- The extension API is PHP 8.0.30's: PHP API 20200930 and Zend extension
API 420200930. An extension built for PHP 8.0 elsewhere loads as before.
To build one that NES does not ship, install
php8.0-devand usephpize8.0andphp-config8.0. Withpecl(Ubuntu'sphp-pear), first runpecl config-set php_bin /usr/bin/php8.0andpecl config-set php_suffix 8.0. APCu builds and runs this way. - Report a suspected vulnerability in NES for PHP privately to HeroDevs at
support@herodevs.com. Include the output of
php8.0 -v, the package versions (dpkg -l 'php8.0*') and the steps that reproduce it.