PHP Issues Second Windows Security Update in Five Days to Fix Brotli Code Execution Flaw
PHP rebuilt its official Windows packages for versions 8.2 through 8.5. The important change is inside the package: Brotli was updated from affected version 1.2.0 to fixed version 1.2.1. The PHP source itself stayed the same, so the earlier PHP2Shell remote code execution fixes remain included. The replacement packages are numbered 8.5.12-1, 8.4.27-1, 8.3.36-1 and 8.2.35-1. They were needed because the October 21 releases still shipped Brotli 1.2.0, according to their software bills of materials. That library flaw can cause memory corruption and potentially allow code execution when reached through automatic HTTP decompression. The five-day gap reflects a packaging correction, not a new PHP language release. Windows users should download the rebuilt files and verify the “-1” filename and published SHA-256 hash. The PHP version shown by php -v remains unchanged because only an included dependency was replaced.
What did PHP change in its new Windows packages, and why was a second update needed only five days after the previous release?
PHP rebuilt its official Windows packages for versions 8.2 through 8.5. The important change is inside the package: Brotli was updated from affected version 1.2.0 to fixed version 1.2.1. The PHP source itself stayed the same, so the earlier PHP2Shell remote code execution fixes remain included.
The replacement packages are numbered 8.5.12-1, 8.4.27-1, 8.3.36-1 and 8.2.35-1. They were needed because the October 21 releases still shipped Brotli 1.2.0, according to their software bills of materials. That library flaw can cause memory corruption and potentially allow code execution when reached through automatic HTTP decompression.
The five-day gap reflects a packaging correction, not a new PHP language release. Windows users should download the rebuilt files and verify the “-1” filename and published SHA-256 hash. The PHP version shown by php -v remains unchanged because only an included dependency was replaced.
What is the Brotli library, and how can a flaw in it allow memory corruption and potentially arbitrary code execution?
Brotli is a compression library included in PHP’s official Windows packages. It helps software handle Brotli-compressed data, reducing the size of HTTP responses before they are transmitted. The library becomes security-sensitive because clients must decode that data after receiving it.
In the affected versions, a specially crafted compressed response can trigger a flaw while Brotli processes the response. PHP describes the result as memory corruption with the potential for code execution. The article does not provide a more specific technical cause, so the key risk is unsafe handling of attacker-controlled compressed input.
The risk is conditional rather than automatic for every PHP request. cURL must be configured to decompress responses, either directly by an application or indirectly through an HTTP client library. Google rated the flaw 9.2, Critical, under CVSS 4.0, while Red Hat rated it 8.1, Important, under CVSS 3.1.
How could a PHP application actually reach the flaw through cURL or Guzzle when processing an HTTP response?
The vulnerable path begins when a PHP application contacts a server and receives a compressed response. cURL normally leaves automatic decompression disabled. An application can change that behavior with the CURLOPT_ENCODING option, allowing cURL to unpack the response before PHP code uses it.
An empty CURLOPT_ENCODING value tells cURL to accept every format it supports. That can include Brotli. Guzzle, a PHP HTTP client library, sets this empty value by default for cURL requests in its 7.16.1 and 8.3.1 code. Therefore, an application using those defaults meets the condition described by PHP.
The attacker’s input is the compressed response, not necessarily the application’s request. A server contacted by the PHP application could send a crafted response, and Brotli would process it during automatic decoding. The Hacker News had not tested this behavior on Windows, and PHP’s notice reported no attacks.
How broad is the affected software base: which PHP versions, Windows builds, Brotli versions, and application settings are involved?
PHP rebuilt official Windows packages for PHP 8.2, 8.3, 8.4 and 8.5. The replacement package numbers are 8.2.35-1, 8.3.36-1, 8.4.27-1 and 8.5.12-1. The affected component was Brotli 1.2.0, shown in the software bills of materials for last week’s x64 Non Thread Safe builds.
The software version alone does not describe every exposed application. The flaw can be reached when cURL automatically decompresses an HTTP response. In PHP, CURLOPT_ENCODING turns that behavior on, and an empty value accepts every format cURL supports. Guzzle’s cited versions set that empty value by default for cURL requests.
Applications using other settings may not meet the stated condition. The fixed packages contain Brotli 1.2.1. Node.js, Bun and other software that ships its own Brotli copy also released fixes, so their exposure depends on their own bundled versions and updates.
What can administrators do if they cannot install the rebuilt packages immediately, and why might simply removing Brotli from the Accept-Encoding header be insufficient?
The safest stated interim measure is to stop automatic decompression until the rebuilt package is installed. In PHP, that means not setting CURLOPT_ENCODING, because cURL does not decompress responses without that option. This avoids the vulnerable processing path described in PHP’s notice.
For Guzzle, administrators can set the decode_content request option to false. That disables all automatic decoding, rather than only Brotli decoding. As a result, gzip responses also arrive compressed and the application must handle that change appropriately.
Simply removing br, Brotli’s name, from the Accept-Encoding header is not enough. Axiom warned that a server can still send Brotli despite that header change. The article gives no other workaround for systems that cannot update, so disabling automatic decoding is the stated temporary protection while administrators obtain the fixed packages.
Why can the PHP version shown by `php -v` stay the same even though the installed package contains an important security fix, and how can the new build be verified?
The rebuilt packages use the same PHP source as the October 21 releases. PHP replaced an included dependency, Brotli, rather than changing the PHP version itself. That is why running php -v can show the same number before and after installation, even though the package now contains an important security fix.
The package filename provides the first practical clue. A corrected file such as php-8.5.12-1-nts-Win32-vs17-x64.zip includes “-1” in its name. The corresponding rebuilt package numbers are 8.5.12-1, 8.4.27-1, 8.3.36-1 and 8.2.35-1.
Users should download the new build from PHP’s downloads page and compare its SHA-256 hash with the value published there. The filename suffix and matching hash distinguish the rebuilt package from last week’s file. The software bill of materials also shows the component change to Brotli 1.2.1.
What happens when an HTTP client requests compressed data, and how do compression libraries such as Brotli fit into the relationship between a server, a client, and an application?
When an application requests an HTTP response, the client can tell the server which compression formats it supports. The server may then send the response in compressed form. This reduces the transmitted data, but the client must decode it before the application can normally use the response content.
cURL handles this exchange when automatic decompression is enabled. CURLOPT_ENCODING controls that behavior, and an empty value accepts every format cURL supports. If the server sends Brotli-compressed data, the client passes it to the Brotli library for decompression. A PHP application using Guzzle can enter this path because Guzzle’s cited defaults set the relevant cURL value.
The relationship has three parts: the server sends compressed bytes, the client receives and decodes them, and the application consumes the resulting response. The security problem occurs during decoding. A crafted server response can therefore affect an application before its normal response-processing logic runs.
This brief was written by AI from the original reporting and checked by other models. Names, figures and quotes come from the source; read it for full context.
Read more in the JupiteX app
Pulse is free. New stories every 4 hours, each one broken into the questions that explain it.
Or read more news on the web