<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Remote Code Execution | FirewallSync</title><link>https://firewallsync.com/tags/remote-code-execution/</link><description>Practical cybersecurity writing for engineering teams that ship fast.</description><language>en-us</language><image><url>https://firewallsync.com/icon-512.png</url><title>FirewallSync</title><link>https://firewallsync.com/</link></image><lastBuildDate>Thu, 29 Oct 2026 04:30:00 +0000</lastBuildDate><atom:link href="https://firewallsync.com/tags/remote-code-execution/index.xml" rel="self" type="application/rss+xml"/><item><title>Magento CVE-2026-48356 (PolyShell): Patch and Hunt</title><link>https://firewallsync.com/posts/magento-cve-2026-48356-polyshell-patch-and-hunt/</link><guid>https://firewallsync.com/posts/magento-cve-2026-48356-polyshell-patch-and-hunt/</guid><pubDate>Thu, 29 Oct 2026 04:30:00 +0000</pubDate><dc:creator>Craig Leslie</dc:creator><category>Security Operations</category><description>CVE-2026-48356 is the PolyShell file-upload flaw in Adobe Commerce and Magento Open Source. CISA added it to the KEV catalog on October 27, 2026. Here are the fixed builds, why a store already on 2.4.9 may still need an update, and the checks that find an existing compromise.</description><enclosure url="https://firewallsync.com/posts/magento-cve-2026-48356-polyshell-patch-and-hunt/cover_hu14701130590101558514.jpg" type="image/jpeg" length="0"/><media:content url="https://firewallsync.com/posts/magento-cve-2026-48356-polyshell-patch-and-hunt/cover_hu14701130590101558514.jpg" medium="image" type="image/jpeg" width="1200" height="630"/><content:encoded><![CDATA[<p><img src="https://firewallsync.com/posts/magento-cve-2026-48356-polyshell-patch-and-hunt/cover_hu14701130590101558514.jpg" alt="Rows of empty grey metal shopping carts with orange handles, nested together against a white wall on a polished concrete floor" width="1200" height="630"></p><p>CVE-2026-48356 is the Magento file-upload flaw that Sansec calls <strong>PolyShell</strong>, and it is now on CISA&rsquo;s <a href="https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-48356">Known Exploited Vulnerabilities catalog</a> (added October 27, 2026; federal due date November 10). Adobe shipped the fix in <a href="https://helpx.adobe.com/security/products/magento/apsb26-73.html">APSB26-73</a> on July 14, 2026. If your store is not on a <code>2026-jul</code> build, update now. If it was exposed for any time since March, hunt as well. Attackers have used the flaw to plant webshells and to inject JavaScript loaders into CMS blocks, and an update removes neither.</p>
<h2 id="what-is-affected-and-what-fixes-it">What is affected and what fixes it</h2>
<p>The table comes from Adobe&rsquo;s <a href="https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/48xxx/CVE-2026-48356.json">CVE record</a> and the APSB26-73 solution table, which agree on the fixed builds.</p>
<table>
  <thead>
      <tr>
          <th>Product</th>
          <th>Affected (up to and including)</th>
          <th>Fixed build</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Adobe Commerce</td>
          <td>2.4.9, 2.4.8-p5, 2.4.7-p10, 2.4.6-p15, 2.4.5-p17, 2.4.4-p18</td>
          <td>2.4.9-2026-jul, 2.4.8-2026-jul, 2.4.7-2026-jul, 2.4.6-2026-jul, 2.4.5-2026-jul, 2.4.4-2026-jul</td>
      </tr>
      <tr>
          <td>Magento Open Source</td>
          <td>2.4.9, 2.4.8-p5, 2.4.7-p10, 2.4.6-p15</td>
          <td>2.4.9-2026-jul, 2.4.8-2026-jul, 2.4.7-2026-jul, 2.4.6-2026-jul</td>
      </tr>
      <tr>
          <td>Adobe Commerce B2B</td>
          <td>1.5.3, 1.5.2-p5, 1.4.2-p10, 1.3.4-p17, 1.3.3-p18</td>
          <td>1.5.3-2026-jul, 1.5.2-2026-jul, 1.4.2-2026-jul, 1.3.4-2026-jul, 1.3.3-2026-jul</td>
      </tr>
      <tr>
          <td>Adobe Commerce Events</td>
          <td>1.20.0 and earlier</td>
          <td>1.21.0</td>
      </tr>
  </tbody>
</table>
<p>Two details matter here.</p>
<p><strong>2.4.9 is listed as affected.</strong> Sansec&rsquo;s <a href="https://sansec.io/research/magento-polyshell">PolyShell write-up</a> says Adobe released the fix in 2.4.9 on May 12, 2026, and backported it to the supported release lines through APSB26-73 on July 14. Adobe&rsquo;s CVE record, however, lists 2.4.9 among the affected versions and 2.4.9-2026-jul as unaffected. We have not diffed the two releases, so we can&rsquo;t say which is right. The safe reading is Adobe&rsquo;s: move to 2.4.9-2026-jul.</p>
<p><strong>Older Open Source lines are not listed at all.</strong> Adobe lists 2.4.4 and 2.4.5 <code>2026-jul</code> builds only for Adobe Commerce. For Magento Open Source 2.4.5 and older, the record names neither an affected nor a fixed version. Don&rsquo;t read that as safe: Sansec says every version up to 2.4.9-alpha2 is affected. If you run one of those lines, plan an upgrade and treat the server-side mitigations below as essential in the meantime.</p>
<p>Check what you run with <code>bin/magento --version</code> or <code>composer show magento/product-community-edition</code> (<code>magento/product-enterprise-edition</code> for Commerce), and compare the result with the table.</p>
<h2 id="how-polyshell-works">How PolyShell works</h2>
<p>Sansec describes the flaw in the REST API&rsquo;s handling of file uploads for cart item custom options, where a product option has type &ldquo;file&rdquo;. The most exposed routes are the unauthenticated guest-cart ones:</p>
<ul>
<li><code>POST /V1/guest-carts/:cartId/items</code></li>
<li><code>PUT /V1/guest-carts/:cartId/items/:itemId</code></li>
</ul>
<p>Uploaded files are written to <code>pub/media/custom_options/quote/</code>. Sansec says the GraphQL mutations use a different code path and are not vulnerable.</p>
<p>What an upload leads to depends on the server. Sansec lists code execution through an uploaded PHP file for Apache before 2.3.5 without <code>php_flag engine 0</code>, for stock nginx configs on 2.0.0 to 2.2.x, and for any nginx config that passes every <code>.php</code> request to PHP-FPM. Stored XSS is possible on versions before 2.3.5 and on custom web server configurations.</p>
<p>Adobe describes the same CVE differently. The CVE record says exploitation &ldquo;requires user interaction in that a victim must visit a maliciously crafted URL or interact with a compromised web page&rdquo; and scores it CVSS 3.1 <strong>9.3</strong> (<code>AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N</code>). The regional copy of the bulletin we read shows <strong>9.6</strong> with <code>A:L</code> and labels the impact &ldquo;Privilege escalation&rdquo;. We report both; neither changes the action. A KEV listing outranks the <code>UI:R</code> in the vector. Our <a href="/posts/cvss-vs-epss-vs-kev-which-signal-should-decide-what-you-patch-first/">CVSS vs EPSS vs KEV guide</a> explains why.</p>
<h2 id="what-attackers-have-done-with-it">What attackers have done with it</h2>
<p>Sansec reported a mass wave on March 30, 2026: <a href="https://sansec.io/research/polyshell-mass-attack-wave">471 stores compromised in one hour</a>, with a backdoor named <code>accesson.php</code> dropped across multiple directories and loaders injected into CMS pages and static blocks. That was months before Adobe&rsquo;s July backport.</p>
<p>On October 26, <a href="https://thehackernews.com/2026/10/hackers-infect-953-online-stores-with.html">The Hacker News reported</a> Sansec&rsquo;s findings on a longer campaign: 953 stores infected since July 2025 with a JavaScript loader stored in Magento&rsquo;s <code>cms_block</code> table. Per that report, Sansec attributes 471 of those infections to CVE-2026-48356, and about 102 more to file uploads through PolyShell or CVE-2025-54236 (SessionReaper). One store on 2.4.7-p10 with no missing core patches was compromised through a rogue administrator account. The report also describes webshells disguised as PNG files in <code>pub/media/custom_options/quote/</code>. The loader&rsquo;s final payload is not known.</p>
<p>These figures are Sansec&rsquo;s, as reported by The Hacker News. CISA&rsquo;s catalog entry does not say who is exploiting the flaw, and lists known ransomware use as &ldquo;Unknown&rdquo;.</p>
<h2 id="step-1-install-the-fixed-build">Step 1: Install the fixed build</h2>
<p>Update to the <code>2026-jul</code> build for your release line, then redeploy static content and clear caches as your normal release process requires. If you can&rsquo;t update this week, do steps 2 and 3 now anyway: they limit what a successful upload can do and tell you whether one has already happened.</p>
<p>Sansec suggests a WAF rule that blocks the vulnerable API calls. That buys time, but it is a mitigation, not a fix.</p>
<h2 id="step-2-make-sure-uploads-cant-be-served-or-executed">Step 2: Make sure uploads can&rsquo;t be served or executed</h2>
<p>Magento ships deny rules for this directory. Check that your live config still has them.</p>
<p><strong>nginx.</strong> The stock <a href="https://github.com/magento/magento2/blob/2.4-develop/nginx.conf.sample"><code>nginx.conf.sample</code></a> in the 2.4-develop branch denies the directory and only hands named entry points to PHP. These are excerpts from that file, not a complete config:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">location</span> <span style="color:#e6db74">/media/custom_options/</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">deny</span> <span style="color:#e6db74">all</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">location</span> ~ <span style="color:#e6db74">^/(index|get|static|errors/report|errors/404|errors/503|health_check)\.php$</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># ... fastcgi_pass to PHP-FPM ...
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Banned locations (only reached if the earlier PHP entry point regexes don&#39;t match)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">location</span> ~<span style="color:#e6db74">*</span> <span style="color:#e6db74">(\.php</span>$|\.phtml$|\.htaccess$|\.htpasswd$|\.git<span style="color:#e6db74">)</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">deny</span> <span style="color:#e6db74">all</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The risky pattern is a hand-written or hosting-panel config with a generic <code>location ~ \.php$ { fastcgi_pass ...; }</code> and no deny for <code>/media/custom_options/</code>. With that, a PHP file uploaded to the directory is executed. Sansec recommends a <code>deny all</code> location for <code>custom_options</code> placed before any <code>\.php$</code> block.</p>
<p><strong>Apache.</strong> The repository ships <code>pub/media/custom_options/.htaccess</code> containing <code>Require all denied</code> (Apache 2.4) or <code>deny from all</code> (older). Confirm it exists on disk and that <code>AllowOverride</code> lets Apache read it. Sansec also recommends <code>php_flag engine 0</code> there.</p>
<p>Neither rule stops the upload. Both stop the uploaded file from being fetched or run through the web server.</p>
<h2 id="step-3-hunt-for-an-existing-compromise">Step 3: Hunt for an existing compromise</h2>
<p>Run these from the Magento root, or adjust the paths. Sansec published the first checks; we added the database queries.</p>
<p><strong>Files in the upload directory.</strong> Customer uploads can be legitimate, but any script file there is a strong sign of compromise:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Everything uploaded through custom options, newest first</span>
</span></span><span style="display:flex;"><span>find pub/media/custom_options/ -type f ! -name <span style="color:#e6db74">&#39;.htaccess&#39;</span> -printf <span style="color:#e6db74">&#39;%TY-%Tm-%Td %TH:%TM  %s  %p\n&#39;</span> | sort -r | head -50
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Script extensions there are a red flag</span>
</span></span><span style="display:flex;"><span>find pub/media/custom_options/ -type f <span style="color:#ae81ff">\(</span> -iname <span style="color:#e6db74">&#39;*.php*&#39;</span> -o -iname <span style="color:#e6db74">&#39;*.phtml&#39;</span> -o -iname <span style="color:#e6db74">&#39;*.phar&#39;</span> <span style="color:#ae81ff">\)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># The backdoor name from the March wave, anywhere in the docroot tree</span>
</span></span><span style="display:flex;"><span>find /var/www -name <span style="color:#e6db74">&#39;accesson.php&#39;</span> -type f
</span></span></code></pre></div><p>The October report describes webshells disguised as <code>.png</code>. A PNG that starts with <code>&lt;?php</code> is not an image. Check with <code>file</code> or <code>head -c 64</code> on anything recent in that directory.</p>
<p><strong>Injected scripts in CMS content.</strong> The loader lives in the database, so file scans miss it. Run this against a replica or read-only connection (add your table prefix if you use one):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">SELECT</span> <span style="color:#e6db74">&#39;block&#39;</span> <span style="color:#66d9ef">AS</span> kind, block_id <span style="color:#66d9ef">AS</span> id, identifier, update_time
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span> cms_block
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WHERE</span> content <span style="color:#66d9ef">LIKE</span> <span style="color:#e6db74">&#39;%&lt;script%&#39;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">OR</span> content <span style="color:#66d9ef">LIKE</span> <span style="color:#e6db74">&#39;%deepveindrilling%&#39;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">OR</span> content <span style="color:#66d9ef">LIKE</span> <span style="color:#e6db74">&#39;%lanhd6549tdhse%&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">UNION</span> <span style="color:#66d9ef">ALL</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">SELECT</span> <span style="color:#e6db74">&#39;page&#39;</span>, page_id, identifier, update_time
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span> cms_page
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WHERE</span> content <span style="color:#66d9ef">LIKE</span> <span style="color:#e6db74">&#39;%&lt;script%&#39;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">OR</span> content <span style="color:#66d9ef">LIKE</span> <span style="color:#e6db74">&#39;%deepveindrilling%&#39;</span>
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">OR</span> content <span style="color:#66d9ef">LIKE</span> <span style="color:#e6db74">&#39;%lanhd6549tdhse%&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">ORDER</span> <span style="color:#66d9ef">BY</span> update_time <span style="color:#66d9ef">DESC</span>;
</span></span></code></pre></div><p>Column names come from Magento&rsquo;s <code>Cms</code> module schema; we checked the query&rsquo;s syntax against a small SQLite copy of those tables, not against a live MySQL store. Many stores have legitimate scripts in CMS blocks, so review hits by <code>update_time</code> and by where the script loads from. The October report lists these loader domains: <code>manulfie[.]click</code>, <code>neswnsssn[.]click</code>, <code>lanhd6549tdhse[.]top</code>, <code>additionalver[.]com</code> and <code>deepveindrilling[.]com</code>. Sansec&rsquo;s March write-up adds <code>jslibrary[.]net</code> and <code>canevaslab[.]com</code>. Add any you want to the <code>LIKE</code> list.</p>
<p><strong>Admin accounts you didn&rsquo;t create.</strong> One store in the October report was compromised through a rogue admin:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#66d9ef">SELECT</span> user_id, username, email, created, logdate, is_active
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span> admin_user
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">WHERE</span> created <span style="color:#f92672">&gt;=</span> <span style="color:#e6db74">&#39;2026-03-01&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">ORDER</span> <span style="color:#66d9ef">BY</span> created <span style="color:#66d9ef">DESC</span>;
</span></span></code></pre></div><p><strong>Web logs.</strong> Look for requests to the guest-cart item routes, which usually sit under <code>/rest/V1/</code> or <code>/rest/&lt;store_code&gt;/V1/</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>grep -E <span style="color:#e6db74">&#39;&#34;(POST|PUT) /rest/([a-z0-9_]+/)?V1/guest-carts/[^/ ]+/items&#39;</span> /var/log/nginx/access.log* | head
</span></span></code></pre></div><p>Headless storefronts call these routes legitimately, so a hit is not proof. Line up timestamps with new files in <code>pub/media/custom_options/quote/</code> and with <code>cms_block</code> updates.</p>
<p>If you find a webshell or an injected loader, treat the store as compromised. Remove the artifacts, rotate admin, database and integration credentials, check for other persistence (cron, other PHP files, modified <code>app/etc/env.php</code>), and consider your payment-card obligations, since these loaders run in shoppers&rsquo; browsers. Our <a href="/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/">PHP2Shell response guide</a> covers the server-side hunt for PHP webshells in more detail.</p>
<h2 id="hardening-after-the-patch">Hardening after the patch</h2>
<ul>
<li>Keep <code>pub/</code> as the document root and let PHP run only for Magento&rsquo;s named entry points. Sansec&rsquo;s RCE conditions are old releases or web server configs that execute PHP files in upload directories.</li>
<li>Turn off PHP execution in every writable media directory, not just this one. Our <a href="/posts/php-ini-security-hardening-production-settings/">php.ini hardening guide</a> covers related settings.</li>
<li>If you don&rsquo;t use file-type custom options, Sansec&rsquo;s WAF suggestion is cheap: block file uploads to the guest-cart item routes.</li>
<li>Monitor <code>cms_block</code> and <code>cms_page</code> for changes. A loader injected through the database survives code deploys.</li>
</ul>
<h2 id="limits-of-this-article">Limits of this article</h2>
<p>We did not reproduce the exploit or diff the patched releases. Affected and fixed versions come from Adobe&rsquo;s CVE record and bulletin. The upload mechanics, server conditions and campaign figures come from Sansec, the latter through The Hacker News. The <code>adobe.com/trust</code> copy of APSB26-73 could not be retrieved during research; we used Adobe&rsquo;s regional <code>helpx</code> copy, which shows &ldquo;Last updated on 14 July 2026&rdquo; and may not reflect later revisions. We ran the <code>find</code> and <code>grep</code> commands against a mock directory tree and sample log lines, and the SQL against SQLite, not against a production store.</p>
<h2 id="sources-and-verification">Sources and verification</h2>
<table>
  <thead>
      <tr>
          <th>Important claim</th>
          <th>Source</th>
          <th>Status</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>KEV addition 2026-10-27, due 2026-11-10, CWE-434, ransomware use &ldquo;Unknown&rdquo;</td>
          <td><a href="https://github.com/cisagov/kev-data/blob/main/known_exploited_vulnerabilities.json">CISA KEV catalog (kev-data)</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Affected and unaffected versions; CVSS 3.1 9.3 vector; &ldquo;requires user interaction&rdquo;</td>
          <td><a href="https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/48xxx/CVE-2026-48356.json">CVE-2026-48356 record</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>CISA SSVC Exploitation &ldquo;active&rdquo;</td>
          <td>CISA ADP in the same CVE record</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Published July 14, 2026; priority 2; fixed builds; 9.6 score; &ldquo;not aware of any exploits&rdquo; at publication</td>
          <td><a href="https://helpx.adobe.com/security/products/magento/apsb26-73.html">Adobe APSB26-73</a> (regional helpx copy)</td>
          <td>Qualified: regional copy</td>
      </tr>
      <tr>
          <td>Guest-cart REST routes, upload path, RCE conditions, 2.4.9 fix and July backport</td>
          <td><a href="https://sansec.io/research/magento-polyshell">Sansec: PolyShell</a></td>
          <td>Qualified: researcher&rsquo;s account</td>
      </tr>
      <tr>
          <td>471 stores in one hour on March 30, 2026; accesson.php</td>
          <td><a href="https://sansec.io/research/polyshell-mass-attack-wave">Sansec: mass PolyShell wave</a></td>
          <td>Qualified: researcher&rsquo;s account</td>
      </tr>
      <tr>
          <td>953-store campaign; 471 via CVE-2026-48356; loader domains</td>
          <td><a href="https://thehackernews.com/2026/10/hackers-infect-953-online-stores-with.html">The Hacker News, Oct 26, 2026</a> citing Sansec</td>
          <td>Qualified: press report</td>
      </tr>
      <tr>
          <td>Stock nginx deny rules; custom_options .htaccess; cms_block / admin_user columns</td>
          <td><a href="https://github.com/magento/magento2/tree/2.4-develop">magento/magento2 2.4-develop</a></td>
          <td>Verified</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>Brotli CVE-2026-111497: Find and Patch Every Copy</title><link>https://firewallsync.com/posts/brotli-cve-2026-111497-find-and-patch-every-copy/</link><guid>https://firewallsync.com/posts/brotli-cve-2026-111497-find-and-patch-every-copy/</guid><pubDate>Wed, 28 Oct 2026 04:40:00 +0000</pubDate><dc:creator>John Marshall</dc:creator><category>Security Operations</category><description>CVE-2026-111497 is an out-of-bounds write in Google's Brotli decoder, now on CISA's KEV list. It ships inside Node.js, Python packages, Go modules, Envoy and more, and patched builds can still report the old Brotli version. Here is how to find every copy and check it for the fix.</description><enclosure url="https://firewallsync.com/posts/brotli-cve-2026-111497-find-and-patch-every-copy/cover_hu14059145143623990521.jpg" type="image/jpeg" length="0"/><media:content url="https://firewallsync.com/posts/brotli-cve-2026-111497-find-and-patch-every-copy/cover_hu14059145143623990521.jpg" medium="image" type="image/jpeg" width="1200" height="630"/><content:encoded><![CDATA[<p><img src="https://firewallsync.com/posts/brotli-cve-2026-111497-find-and-patch-every-copy/cover_hu14059145143623990521.jpg" alt="Round straw bales stacked in tight columns, each bound with thin blue netting" width="1200" height="630"></p><p>CVE-2026-111497 is a memory-corruption bug in Google&rsquo;s Brotli decompressor. Upstream versions 1.0.3 through 1.2.0 are affected, and 1.0.10, 1.1.1 and 1.2.1 fix it. CISA added it to the <a href="https://www.cisa.gov/known-exploited-vulnerabilities-catalog">Known Exploited Vulnerabilities catalog</a> on October 27, 2026, with a federal remediation date of November 10. The hard part is not the patch. Brotli is compiled into Node.js, Python wheels, Go modules, proxies and service meshes, and several patched builds still report the old version number. Here is where it hides, what &ldquo;fixed&rdquo; looks like for each, and a tested way to check code you vendor yourself.</p>
<h2 id="are-you-affected">Are you affected?</h2>
<p>You are exposed if a vulnerable Brotli decoder processes data an attacker can supply. The <a href="https://www.cve.org/CVERecord?id=CVE-2026-111497">CVE record</a> says an attacker with &ldquo;a crafted Brotli-compressed stream&rdquo; can &ldquo;corrupt adjacent decoder state memory, disclose sensitive memory contents, cause a denial of service, or potentially execute arbitrary code&rdquo;. Google&rsquo;s CNA scored it CVSS 4.0 9.2 (Critical). The Node.js project rates its copy High.</p>
<table>
  <thead>
      <tr>
          <th>Where Brotli lives</th>
          <th>Affected</th>
          <th>Fixed in</th>
          <th>How to check</th>
          <th>Source</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Google Brotli / libbrotli</td>
          <td>1.0.3 to 1.2.0</td>
          <td>1.0.10, 1.1.1, 1.2.1</td>
          <td>Package version, or the code check below for vendored copies</td>
          <td>CVE record, upstream CHANGELOG</td>
      </tr>
      <tr>
          <td>Node.js 22, 24, 26</td>
          <td>Earlier builds on those lines</td>
          <td>22.23.4, 24.22.1, 26.12.1</td>
          <td><code>node -v</code> (not <code>process.versions.brotli</code>)</td>
          <td>Node.js advisory</td>
      </tr>
      <tr>
          <td>End-of-life Node.js</td>
          <td>Assume affected</td>
          <td>None: upgrade</td>
          <td><code>node -v</code></td>
          <td>Node.js advisory</td>
      </tr>
      <tr>
          <td>Python <code>Brotli</code></td>
          <td>1.0.3 to 1.2.0</td>
          <td>1.2.1</td>
          <td><code>pip show Brotli</code></td>
          <td>Aikido; PyPI release date</td>
      </tr>
      <tr>
          <td>Python <code>brotlicffi</code></td>
          <td>1.2.0.x</td>
          <td>1.2.1.0</td>
          <td><code>pip show brotlicffi</code></td>
          <td>Aikido; PyPI release date</td>
      </tr>
      <tr>
          <td>Go <code>github.com/andybalholm/brotli</code></td>
          <td>Before v1.2.7</td>
          <td>v1.2.7</td>
          <td><code>go list -m github.com/andybalholm/brotli</code></td>
          <td>CVE record reference, source diff</td>
      </tr>
      <tr>
          <td>Envoy</td>
          <td>1.36.11, 1.37.7, 1.38.5, 1.39.2</td>
          <td>1.36.12, 1.37.8, 1.38.6, 1.39.3, 1.40.0</td>
          <td><code>envoy --version</code></td>
          <td>Wiz (qualified); we checked 1.39.2 against 1.39.3</td>
      </tr>
      <tr>
          <td>Istio</td>
          <td>1.29.0 to 1.29.8, 1.30.0 to 1.30.5, 1.31.0 to 1.31.1</td>
          <td>1.29.9, 1.30.6, 1.31.2</td>
          <td><code>istioctl version</code></td>
          <td>Wiz (qualified)</td>
      </tr>
      <tr>
          <td>Bun</td>
          <td>1.0.21 to 1.4.3</td>
          <td>1.4.4</td>
          <td><code>bun --version</code></td>
          <td>Wiz (qualified)</td>
      </tr>
      <tr>
          <td>Distro packages (libbrotli1, brotli)</td>
          <td>Depends on backport</td>
          <td>Distro security update</td>
          <td>Your distro&rsquo;s security tracker</td>
          <td>—</td>
      </tr>
  </tbody>
</table>
<p>The Envoy, Istio and Bun ranges come from <a href="https://www.wiz.io/blog/cve-2026-111497-brotli-rce-node-js">Wiz&rsquo;s write-up</a>, not from those projects&rsquo; advisories. We did not read those advisories directly. For Envoy we checked the source instead: <code>bazel/repository_locations.bzl</code> pins Brotli <code>1.2.0</code> at tag v1.39.2, while v1.39.3 pins a Brotli commit whose <code>decode.c</code> contains the fix.</p>
<p>Linux distributions usually backport fixes and keep the upstream version. Our Ubuntu 24.04 sandbox, for example, has <code>libbrotli1 1.1.0-2ubuntu0.1</code>. That string alone does not tell you whether the fix is in. Use your distribution&rsquo;s security tracker for the CVE.</p>
<h3 id="why-the-version-string-can-mislead-you">Why the version string can mislead you</h3>
<p>Node.js patched its bundled Brotli in place. On the fixed Node.js 22.23.4 the reported library version is still the old one:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ node -v
</span></span><span style="display:flex;"><span>v22.23.4
</span></span><span style="display:flex;"><span>$ node -p process.versions.brotli
</span></span><span style="display:flex;"><span>1.1.0
</span></span></code></pre></div><p>We ran that in our sandbox. The source tree agrees: <code>deps/brotli/c/common/version.h</code> declares 1.1.0 at both v22.23.3 and v22.23.4, and 1.2.0 at v24.22.1 and v26.12.1, but only the fixed tags contain the patched decoder (v22.23.3 and v24.22.0 do not). A scanner that flags <code>process.versions.brotli &lt; 1.2.1</code> will raise false positives on fixed Node.js. A scanner that trusts a vendored <code>version.h</code> can miss real exposure the other way round. For Node.js, use the Node.js version. For anything else you vendor, check the code.</p>
<h2 id="what-the-bug-is">What the bug is</h2>
<p>The <a href="https://nodejs.org/en/blog/vulnerability/october-2026-security-releases">Node.js advisory</a> gives the clearest description: &ldquo;An invalid block switch was reported as a temporary need for more input instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer.&rdquo;</p>
<p>The upstream diff between v1.2.0 and v1.2.1 of <code>c/dec/decode.c</code> shows exactly that. <code>DecodeBlockTypeAndLength()</code> used to return a plain boolean, so &ldquo;invalid stream&rdquo; and &ldquo;need more input&rdquo; looked the same, and the non-safe callers ignored the result altogether (<code>static void DecodeLiteralBlockSwitch(...)</code>). After the fix the function returns a <code>BrotliDecoderErrorCode</code>, emits <code>BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH</code> for the invalid case, and every caller checks it through a new <code>BROTLI_SAFE_WITH_STATUS</code> macro. That matches the two weaknesses in the CVE record: CWE-252 (unchecked return value) and CWE-787 (out-of-bounds write).</p>
<p>The flaw was found by Khai Tran and Sylvie Mayer of OpenAI Codex Security, who are credited in both the CVE record and the Node.js advisory.</p>
<h2 id="where-untrusted-brotli-reaches-your-code">Where untrusted Brotli reaches your code</h2>
<p>The flaw is in decompression, so look for places that decode data you did not produce:</p>
<ul>
<li><strong>Request bodies.</strong> Any endpoint or middleware that inflates <code>Content-Encoding: br</code> uploads.</li>
<li><strong>Outbound HTTP.</strong> HTTP clients decode Brotli responses for you. If an attacker controls or can redirect the URL (webhooks, link previews, feed fetchers, scrapers), they control the compressed bytes.</li>
<li><strong>Files and archives</strong> that contain Brotli streams.</li>
<li><strong>Proxies and meshes</strong> that decompress traffic to inspect or transform it.</li>
</ul>
<p>Two behaviours we checked, because they mean code that never mentions Brotli can still run it:</p>
<ul>
<li><strong>Node.js <code>fetch()</code> decodes Brotli it never asked for.</strong> On Node.js 22.23.4, <code>fetch()</code> sent <code>accept-encoding: gzip, deflate</code>. When our local test server replied with <code>content-encoding: br</code>, <code>fetch()</code> decompressed the body anyway. A hostile server can choose Brotli whatever the client advertises.</li>
<li><strong>Python&rsquo;s requests turns Brotli on when it is installed.</strong> urllib3&rsquo;s <code>util/request.py</code> appends <code>br</code> to its default <code>Accept-Encoding</code> when <code>brotlicffi</code> or <code>brotli</code> can be imported. With Brotli 1.2.1 installed, <code>requests.utils.default_headers()</code> returned <code>gzip, deflate, br</code> in our test. The decoding then runs in whichever Brotli package is installed.</li>
</ul>
<h2 id="what-to-do-now">What to do now</h2>
<ol>
<li><strong>Update the runtimes.</strong> Node.js to 22.23.4, 24.22.1 or 26.12.1 or later. Move off end-of-life Node.js lines: the advisory notes that &ldquo;End-of-Life versions are always affected when a security release occurs.&rdquo;</li>
<li><strong>Update language packages</strong> in every lockfile and image: <code>Brotli&gt;=1.2.1</code>, <code>brotlicffi&gt;=1.2.1.0</code>, <code>github.com/andybalholm/brotli v1.2.7</code>. Both Python fixes were published to PyPI on October 22, 2026.</li>
<li><strong>Update proxies and meshes</strong> (Envoy, Istio) and Bun to the fixed releases above. Confirm the ranges against each project&rsquo;s own advisory.</li>
<li><strong>Apply distro updates</strong> for <code>libbrotli</code>/<code>brotli</code>, then restart the long-running processes that loaded the old library.</li>
<li><strong>Rebuild container images.</strong> A fixed base image does not help a running container that was built from the old one.</li>
<li><strong>Hunt for vendored copies</strong> with the check below.</li>
</ol>
<p>If you cannot patch a service today, reduce what it decodes. As a stopgap, reject <code>Content-Encoding: br</code> request bodies at the edge for services that do not need them, and stop server-side fetchers from decoding responses from untrusted URLs. This is our editorial suggestion, not vendor guidance, and it does not replace the update.</p>
<h3 id="inventory-commands">Inventory commands</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># Node.js: the version that matters</span>
</span></span><span style="display:flex;"><span>node -v
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Python: every environment and image</span>
</span></span><span style="display:flex;"><span>pip show Brotli brotlicffi 2&gt;/dev/null | grep -E <span style="color:#e6db74">&#39;^(Name|Version)&#39;</span>
</span></span><span style="display:flex;"><span>pipdeptree -r -p Brotli          <span style="color:#75715e"># who pulls it in</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Go modules</span>
</span></span><span style="display:flex;"><span>go list -m all | grep andybalholm/brotli
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Debian/Ubuntu and RHEL-family system libraries</span>
</span></span><span style="display:flex;"><span>dpkg -l <span style="color:#e6db74">&#39;libbrotli*&#39;</span> 2&gt;/dev/null | awk <span style="color:#e6db74">&#39;/^ii/{print $2, $3}&#39;</span>
</span></span><span style="display:flex;"><span>rpm -q brotli libbrotli 2&gt;/dev/null
</span></span></code></pre></div><p>The <code>pip</code>, <code>node</code> and <code>dpkg</code> lines were run in our sandbox. The <code>go</code>, <code>pipdeptree</code> and <code>rpm</code> lines are standard tool usage that we did not run here.</p>
<h3 id="checking-vendored-source-for-the-fix">Checking vendored source for the fix</h3>
<p>C and C++ projects often copy <code>c/dec/decode.c</code> into their tree, and Go programs carry <code>decode.go</code> in the module cache or a <code>vendor/</code> directory. This script looks for the patched function signature instead of trusting any version string:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e"># brotli-fixcheck.sh DIR...: find vendored Brotli decoder sources and report</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># whether they carry the CVE-2026-111497 fix. Looks at the code, not the</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># version string, because patched Node.js still reports the old version.</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> root in <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>  find <span style="color:#e6db74">&#34;</span>$root<span style="color:#e6db74">&#34;</span> <span style="color:#ae81ff">\(</span> -name decode.c -path <span style="color:#e6db74">&#39;*dec*&#39;</span> <span style="color:#ae81ff">\)</span> -o <span style="color:#ae81ff">\(</span> -name decode.go -path <span style="color:#e6db74">&#39;*brotli*&#39;</span> <span style="color:#ae81ff">\)</span> 2&gt;/dev/null |
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">while</span> read -r f; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> grep -q <span style="color:#e6db74">&#39;BrotliDecoderErrorCode DecodeBlockTypeAndLength&#39;</span> <span style="color:#e6db74">&#34;</span>$f<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>       grep -q <span style="color:#e6db74">&#39;func decodeBlockTypeAndLength(.*) int {&#39;</span> <span style="color:#e6db74">&#34;</span>$f<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>      echo <span style="color:#e6db74">&#34;PATCHED    </span>$f<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">elif</span> grep -q <span style="color:#e6db74">&#39;DecodeBlockTypeAndLength\|decodeBlockTypeAndLength&#39;</span> <span style="color:#e6db74">&#34;</span>$f<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>      echo <span style="color:#e6db74">&#34;VULNERABLE </span>$f<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span></code></pre></div><p>We tested it against 12 sources pulled from GitHub: upstream Brotli v1.0.9, v1.0.10, v1.1.0, v1.1.1, v1.2.0 and v1.2.1; Node.js <code>deps/brotli</code> at v22.23.3, v22.23.4, v24.22.0 and v24.22.1; and <code>andybalholm/brotli</code> v1.2.6 and v1.2.7. It reported every fixed release as <code>PATCHED</code> and every earlier one as <code>VULNERABLE</code>. Run it over source trees, <code>vendor/</code> directories and <code>$(go env GOMODCACHE)</code>.</p>
<p>It cannot inspect compiled binaries, and a heavily modified fork may not match either pattern. Treat &ldquo;no output&rdquo; as &ldquo;no recognisable copy found&rdquo;, not as &ldquo;safe&rdquo;.</p>
<h2 id="what-to-hunt-for">What to hunt for</h2>
<p>No vendor or agency has published indicators of compromise for this CVE, and CISA&rsquo;s KEV entry does not require forensic triage (<code>forensicTriage: No</code>). Practical checks:</p>
<ul>
<li><strong>Crashes.</strong> Segfaults or aborts in Node.js, Python or proxy processes since late October, especially in services that fetch remote content or accept compressed uploads.</li>
<li><strong>Unexpected Brotli.</strong> Requests with <code>Content-Encoding: br</code> to endpoints that never receive compressed bodies. Wiz recommends reviewing WAF, application and network logs for suspicious Brotli-compressed traffic.</li>
<li><strong>Outbound fetches</strong> from services that took user-supplied URLs, close in time to a crash.</li>
</ul>
<h2 id="limits-of-this-article">Limits of this article</h2>
<p>We did not reproduce the memory corruption or test any exploit. Our checks cover version strings, source code and HTTP client behaviour in a sandbox: Node.js 22.23.4, Python with Brotli 1.2.1, Ubuntu 24.04. The Envoy, Istio and Bun ranges come from a security vendor&rsquo;s summary. The list of affected software is not complete. Wiz notes that other products that bundle or link vulnerable versions of the Brotli C decoder may also be affected.</p>
<p>For the wider process of keeping dependency updates moving, see <a href="/posts/dependency-audits-without-slowing-down-releases/">dependency audits without slowing down releases</a>. For publishing or reading &ldquo;not affected&rdquo; statements about a library like this, see <a href="/posts/vex-explained-what-a-not-affected-statement-means-and-how-to-read-one/">VEX explained</a>. Last week&rsquo;s <a href="/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/">PHP2Shell patch-and-hunt guide</a> covers the two PHP runtime flaws CISA added to KEV the day before.</p>
<h2 id="sources-and-verification">Sources and verification</h2>
<table>
  <thead>
      <tr>
          <th>Important claim</th>
          <th>Source</th>
          <th>Status</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Affected 1.0.3–1.2.0; fixed 1.0.10, 1.1.1, 1.2.1; CVSS 4.0 9.2; CWE-252/787; credit</td>
          <td><a href="https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/111xxx/CVE-2026-111497.json">CVE-2026-111497 record (cvelistV5)</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>KEV added 2026-10-27, due 2026-11-10, forensicTriage No; SSVC exploitation active</td>
          <td><a href="https://github.com/cisagov/kev-data">CISA KEV data</a>; CISA ADP in the CVE record</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>1.2.1 released 2026-10-21 with the CVE fix; code change</td>
          <td><a href="https://github.com/google/brotli/blob/v1.2.1/CHANGELOG.md">google/brotli CHANGELOG</a>; <code>c/dec/decode.c</code> v1.2.0 vs v1.2.1</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Node.js fixed releases, root cause, EOL statement</td>
          <td><a href="https://nodejs.org/en/blog/vulnerability/october-2026-security-releases">Node.js October 2026 security releases</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Patched Node.js reports the old Brotli version</td>
          <td><code>node -p process.versions.brotli</code> on v22.23.4; <code>deps/brotli</code> at the listed tags</td>
          <td>Verified (our test)</td>
      </tr>
      <tr>
          <td>Go fix in andybalholm/brotli v1.2.7</td>
          <td><a href="https://github.com/andybalholm/brotli/releases/tag/v1.2.7">Release v1.2.7</a>; <code>decode.go</code> v1.2.6 vs v1.2.7</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Python Brotli 1.2.1, brotlicffi 1.2.1.0</td>
          <td><a href="https://www.aikido.dev/blog/python-packages-vulnerable-node2shell-brotli-cve-2026-111497">Aikido</a>; PyPI upload dates 2026-10-22</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>urllib3/requests advertise <code>br</code> when Brotli is installed</td>
          <td><a href="https://github.com/urllib3/urllib3/blob/main/src/urllib3/util/request.py">urllib3 <code>util/request.py</code></a>; our test</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Envoy, Istio, Bun ranges</td>
          <td><a href="https://www.wiz.io/blog/cve-2026-111497-brotli-rce-node-js">Wiz</a>; Envoy <code>repository_locations.bzl</code> at v1.39.2/v1.39.3</td>
          <td>Qualified</td>
      </tr>
      <tr>
          <td>Envoy and other consumers affected</td>
          <td><a href="https://www.openwall.com/lists/oss-security/2026/10/23/25">oss-security, 2026-10-23</a>, <a href="https://www.openwall.com/lists/oss-security/2026/10/24/6">2026-10-24</a></td>
          <td>Verified</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>PHP2Shell CVE-2026-109618 and -109619: Patch, Then Hunt</title><link>https://firewallsync.com/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/</link><guid>https://firewallsync.com/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/</guid><pubDate>Tue, 27 Oct 2026 04:50:00 +0000</pubDate><dc:creator>John Marshall</dc:creator><category>Security Operations</category><description>Two PHP core flaws, CVE-2026-109618 and CVE-2026-109619, allow unauthenticated remote code execution against PHP that serves web requests. CISA added both to the KEV catalog on October 26 with a three-day deadline. Here are the fixed versions, why php -v can mislead you on distribution builds, the stopgaps PHP itself recommends, and what to hunt for.</description><enclosure url="https://firewallsync.com/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/cover_hu12286854602341724834.jpg" type="image/jpeg" length="0"/><media:content url="https://firewallsync.com/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/cover_hu12286854602341724834.jpg" medium="image" type="image/jpeg" width="1200" height="630"/><content:encoded><![CDATA[<p><img src="https://firewallsync.com/posts/php2shell-cve-2026-109618-cve-2026-109619-patch-and-hunt/cover_hu12286854602341724834.jpg" alt="Close-up of yellow barrier tape printed with the word ATTENTION, stretched in front of a blurred orange road sign and greenery" width="1200" height="630"></p><p>CVE-2026-109618 and CVE-2026-109619, which the security community has nicknamed &ldquo;PHP2Shell&rdquo;, are two memory-safety flaws in PHP&rsquo;s core that can give an unauthenticated attacker remote code execution on a server running PHP for the web. The fixes are PHP <strong>8.2.35, 8.3.36, 8.4.27 and 8.5.12</strong>. CISA added both CVEs to its Known Exploited Vulnerabilities (KEV) catalog on October 26, 2026, and gave federal agencies until <strong>October 29</strong> to act.</p>
<p>These are bugs in the PHP interpreter, so they apply regardless of your framework or CMS. If you run PHP behind a web server, update the PHP package today, restart every PHP worker, then look for signs that someone got in first. Everything below comes from the PHP project&rsquo;s advisory and CVE records and CISA&rsquo;s KEV entry unless we say otherwise.</p>
<h2 id="are-you-affected">Are you affected?</h2>
<p>The CVE records list PHP 8.2 before 8.2.35, 8.3 before 8.3.36, 8.4 before 8.4.27 and 8.5 before 8.5.12 as affected. PHP&rsquo;s advisory adds who is at risk: &ldquo;all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed.&rdquo; It rates mod_php highest, &ldquo;with a demonstrated exploit where an unauthenticated request can trigger the attack before any application code runs.&rdquo;</p>
<table>
  <thead>
      <tr>
          <th>Branch</th>
          <th>Vulnerable upstream</th>
          <th>Fixed upstream</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>8.5</td>
          <td>below 8.5.12</td>
          <td>8.5.12</td>
      </tr>
      <tr>
          <td>8.4</td>
          <td>below 8.4.27</td>
          <td>8.4.27</td>
      </tr>
      <tr>
          <td>8.3</td>
          <td>below 8.3.36</td>
          <td>8.3.36</td>
      </tr>
      <tr>
          <td>8.2</td>
          <td>below 8.2.35</td>
          <td>8.2.35</td>
      </tr>
      <tr>
          <td>8.1 and older</td>
          <td>not listed in the CVE records; no upstream fix</td>
          <td>vendor backport, PHP&rsquo;s source backport branches for 7.4/8.0/8.1, or upgrade</td>
      </tr>
  </tbody>
</table>
<p>The CVE records only list 8.2 to 8.5. Do not read that as &ldquo;8.1 is safe&rdquo;: PHP says 8.1 and older &ldquo;no longer receive updates&rdquo; and published source backports for 7.4, 8.0 and 8.1 because of the severity.</p>
<h3 id="why-php--v-can-mislead-you">Why <code>php -v</code> can mislead you</h3>
<p>Most production PHP comes from a distribution or a container base image, and those vendors backport fixes without changing the upstream version number. PHP says Linux distributions and LTS vendors &ldquo;received the patches in advance&rdquo;.</p>
<p>We checked an Ubuntu 24.04 host. <code>php -v</code> reports 8.3.6, which is far below 8.3.36, yet the package changelog shows the fix:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ dpkg -l php8.3-cli | tail -1 | awk <span style="color:#e6db74">&#39;{print $2, $3}&#39;</span>
</span></span><span style="display:flex;"><span>php8.3-cli 8.3.6-0ubuntu0.24.04.13
</span></span><span style="display:flex;"><span>$ zcat /usr/share/doc/php8.3-cli/changelog.Debian.gz | head -4
</span></span><span style="display:flex;"><span>php8.3 (8.3.6-0ubuntu0.24.04.13) noble-security; urgency=medium
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>  * SECURITY UPDATE: Remote RCE via state corruption issue
</span></span><span style="display:flex;"><span>    - debian/patches/CVE-2026-109618_109619.patch: Avoid state corruption via
</span></span></code></pre></div><p>So for a distribution build, search the package changelog for the CVE IDs. On Debian or Ubuntu, <code>zcat /usr/share/doc/php*-common/changelog.Debian.gz | grep -m1 CVE-2026-109618</code> works; on RPM-based systems the equivalent is <code>rpm -q --changelog &lt;php package&gt; | grep CVE-2026-109618</code> (illustrative; we did not run the RPM form). For official <code>php</code> Docker images and source builds, the upstream version is the one that counts.</p>
<p>Also check the binary that actually serves traffic. The CLI, <code>php-fpm</code> and <code>libapache2-mod-php</code> can come from different packages and be updated at different times.</p>
<h3 id="a-version-check-for-upstream-builds">A version check for upstream builds</h3>
<p>This script compares upstream version strings against the fixed releases. We ran it with PHP 8.3 CLI (<code>php php2shell-check.php 8.2.34 8.4.27 8.1.31</code>). It cannot see distribution backports, so a &ldquo;VULNERABLE&rdquo; result on a distro build means &ldquo;check the changelog&rdquo;, not &ldquo;definitely exposed&rdquo;.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Compares upstream PHP versions with the fixed releases for
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// CVE-2026-109618 / CVE-2026-109619. Does not detect vendor backports.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>$fixed <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#39;8.2&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;8.2.35&#39;</span>, <span style="color:#e6db74">&#39;8.3&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;8.3.36&#39;</span>, <span style="color:#e6db74">&#39;8.4&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;8.4.27&#39;</span>, <span style="color:#e6db74">&#39;8.5&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;8.5.12&#39;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">status</span>(<span style="color:#a6e22e">string</span> $v, <span style="color:#66d9ef">array</span> $fixed)<span style="color:#f92672">:</span> <span style="color:#a6e22e">string</span> {
</span></span><span style="display:flex;"><span>    $branch <span style="color:#f92672">=</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#39;.&#39;</span>, <span style="color:#a6e22e">array_slice</span>(<span style="color:#a6e22e">explode</span>(<span style="color:#e6db74">&#39;.&#39;</span>, $v), <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>));
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">isset</span>($fixed[$branch])) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">version_compare</span>($v, <span style="color:#e6db74">&#39;8.2&#39;</span>, <span style="color:#e6db74">&#39;&lt;&#39;</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">?</span> <span style="color:#e6db74">&#39;END OF LIFE: no upstream fix; needs vendor backport or upgrade&#39;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;UNKNOWN branch: check php.net&#39;</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">version_compare</span>($v, $fixed[$branch], <span style="color:#e6db74">&#39;&gt;=&#39;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">?</span> <span style="color:#e6db74">&#34;fixed upstream (&gt;= </span><span style="color:#e6db74">{</span>$fixed[$branch]<span style="color:#e6db74">}</span><span style="color:#e6db74">)&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;VULNERABLE upstream (&lt; </span><span style="color:#e6db74">{</span>$fixed[$branch]<span style="color:#e6db74">}</span><span style="color:#e6db74">) unless your vendor backported the fix&#34;</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">foreach</span> (<span style="color:#a6e22e">array_slice</span>($argv, <span style="color:#ae81ff">1</span>) <span style="color:#f92672">?:</span> [<span style="color:#66d9ef">PHP_VERSION</span>] <span style="color:#66d9ef">as</span> $v) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;%-10s %s</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, $v, <span style="color:#a6e22e">status</span>($v, $fixed));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ php php2shell-check.php 8.2.34 8.4.27 8.1.31
</span></span><span style="display:flex;"><span>8.2.34     VULNERABLE upstream (&lt; 8.2.35) unless your vendor backported the fix
</span></span><span style="display:flex;"><span>8.4.27     fixed upstream (&gt;= 8.4.27)
</span></span><span style="display:flex;"><span>8.1.31     END OF LIFE: no upstream fix; needs vendor backport or upgrade
</span></span></code></pre></div><h2 id="what-the-two-flaws-do">What the two flaws do</h2>
<p>Both bugs leave PHP&rsquo;s internal request state inconsistent and let later code trust it.</p>
<ul>
<li><strong>CVE-2026-109618, &ldquo;RCE via OOM corruption&rdquo;.</strong> The CVE record says PHP &ldquo;uses longjmp() for out-of-memory (OOM) errors to exit the current context&rdquo;. Some code paths &ldquo;leave request memory in an uninitialized state before performing an allocation&rdquo;, and &ldquo;the subsequent request cleanup procedure may read or branch on this memory.&rdquo; An attacker who can push a request into an out-of-memory failure at the right moment can trigger it.</li>
<li><strong>CVE-2026-109619, &ldquo;RCE via stale global state&rdquo;.</strong> Global state that &ldquo;temporarily points into request memory&rdquo; may not be reset, so it &ldquo;may refer to request memory even after it has been freed.&rdquo; PHP&rsquo;s advisory explains the consequence: &ldquo;A later request handled by the same worker may use that stale state before normal initialization resets it.&rdquo;</li>
</ul>
<p>Both carry a CVSS v4.0 base score of 9.2 (<code>AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H</code>): network-reachable, no privileges, no user interaction, but high attack complexity with attack requirements present. If you want to decode the vector, see our guide to <a href="/posts/how-to-read-a-cvss-v4-0-vector-string-metric-by-metric-with-real-cve-records/">reading a CVSS v4.0 vector string</a>. The fix shipped in all four branches as one change, described in PHP&rsquo;s NEWS file as &ldquo;Avoid state corruption via bailout&rdquo;.</p>
<p>Credits in the CVE records name Wiz, Ryan at Calif.io and OpenAI as reporters or finders.</p>
<h2 id="exploitation-status">Exploitation status</h2>
<p>The public picture is mixed, so here is what each source says:</p>
<table>
  <thead>
      <tr>
          <th>Date</th>
          <th>Source</th>
          <th>What it says</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Oct 17</td>
          <td>Amazon Threat Intelligence, as reported by Infosecurity Magazine</td>
          <td>An exploitation attempt against its MadPot honeypot &ldquo;dating October 17&rdquo;, four days before disclosure</td>
      </tr>
      <tr>
          <td>Oct 21</td>
          <td>PHP advisory</td>
          <td>A demonstrated exploit against mod_php; patches released</td>
      </tr>
      <tr>
          <td>Oct 21</td>
          <td>oss-security disclosure</td>
          <td>&ldquo;a complete FPM exploit has not been demonstrated&rdquo;, though source analysis suggests FPM is susceptible</td>
      </tr>
      <tr>
          <td>Oct 21</td>
          <td>VulnCheck</td>
          <td>Scanning with a <code>php2shell-scan/109618</code> user agent, and one attempt that &ldquo;tried to (unsuccessfully) drop a webshell via a server-side session file&rdquo;</td>
      </tr>
      <tr>
          <td>Oct 23</td>
          <td>Security Affairs, citing honeypot operators</td>
          <td>&ldquo;no successful remote code execution has been confirmed in real-world attacks&rdquo;</td>
      </tr>
      <tr>
          <td>Oct 23</td>
          <td>FBI IC3 public service announcement</td>
          <td>Updates &ldquo;should be applied immediately&rdquo;</td>
      </tr>
      <tr>
          <td>Oct 26</td>
          <td>CISA KEV</td>
          <td>Both CVEs added; due October 29; forensic triage required for federal agencies</td>
      </tr>
  </tbody>
</table>
<p>CISA&rsquo;s Vulnrichment SSVC entry in the CVE records, dated October 21, still says <code>Exploitation: none</code>. That predates the KEV listing. For how these signals usually relate, see <a href="/posts/cvss-vs-epss-vs-kev-which-signal-should-decide-what-you-patch-first/">CVSS vs EPSS vs KEV</a>.</p>
<p>Our reading: mass scanning started within hours, working exploits exist, and CISA has listed both as exploited. Whether specific attacks succeeded against production servers is not yet established in public sources. That uncertainty is a reason to hunt after patching, not a reason to wait.</p>
<h2 id="what-to-do-now">What to do now</h2>
<ol>
<li><strong>Inventory.</strong> Find every PHP runtime that serves HTTP: VMs, containers, base images, appliances with embedded PHP, and managed hosting. Container images need a rebuild and redeploy; patching the host does nothing for them.</li>
<li><strong>Update.</strong> Move to 8.2.35, 8.3.36, 8.4.27, 8.5.12 or your vendor&rsquo;s patched package. For 8.1 and older, use a vendor backport or upgrade. PHP 8.2 itself reaches end of life on December 31, 2026, according to PHP&rsquo;s release notes, so plan that upgrade too.</li>
<li><strong>Restart every worker.</strong> CVE-2026-109619 is about state that persists across requests in the same worker. Restart PHP-FPM pools, Apache (for mod_php) and any long-running PHP servers after the package update.</li>
<li><strong>Prioritise internet-facing mod_php</strong>, then FPM behind public web servers, then internal applications.</li>
</ol>
<h3 id="if-you-cannot-update-today">If you cannot update today</h3>
<p>PHP lists stopgaps and is explicit that &ldquo;only an update is a complete solution&rdquo; and these &ldquo;do not make an installation safe&rdquo;:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#75715e">; php.ini or FPM pool config, applied before request parsing, then restart workers.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; Illustrative: check each value against your application&#39;s needs.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; CVE-2026-109618 (OOM corruption)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; In an FPM pool use php_admin_value[memory_limit] = -1 so applications can&#39;t override it.</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">memory_limit</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">-1</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; 8M if the app takes no uploads, 32M if it needs them; keep upload_max_filesize below it</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">post_max_size</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">8M</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">upload_max_filesize</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">2M</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; CVE-2026-109619 (stale global state)</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">session.upload_progress.enabled</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">0</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; PHP 8.5 only:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">; fatal_error_backtraces = 0</span>
</span></span></code></pre></div><p>The reasoning behind each, from the advisory:</p>
<ul>
<li><code>memory_limit=-1</code> &ldquo;removes the controllable PHP memory limit failure, but an underlying allocation failure can still reach the vulnerable path.&rdquo; With no PHP memory limit, a container or cgroup memory limit becomes your availability boundary. PHP warns: &ldquo;Do not substitute <code>RLIMIT_AS</code> or <code>RLIMIT_DATA</code>, as these can cause the vulnerable allocation failure.&rdquo;</li>
<li>Low <code>post_max_size</code>, plus limits at the web server or proxy on decoded request size, field count, multipart part count, header count and nesting depth. These &ldquo;must also cover requests without a usable <code>Content-Length</code>.&rdquo;</li>
<li><code>session.upload_progress.enabled=0</code> &ldquo;blocks the confirmed session paths but not other variants&rdquo;. Set it in <code>php.ini</code>, the FPM pool or server config; PHP says &ldquo;Do not rely on <code>ini_set()</code> or FPM <code>.user.ini</code>.&rdquo;</li>
<li>Hiding errors does not help: &ldquo;Hiding diagnostics with <code>error_reporting</code>, <code>display_errors</code> or <code>@</code> does not help.&rdquo;</li>
</ul>
<p><code>php_admin_value</code> matters here because, per the PHP-FPM documentation, &ldquo;Settings defined with php_admin_value and php_admin_flag cannot be overridden with ini_set.&rdquo;</p>
<h2 id="what-to-hunt-for-after-patching">What to hunt for after patching</h2>
<p>Patching removes the bug, not an attacker who already used it. Preserve web server and PHP logs before you rotate or rebuild anything. The indicators below come from VulnCheck&rsquo;s published honeypot observations. They describe scanners and one attempt; real attackers can change every one of them.</p>
<ul>
<li><strong>User agents:</strong> <code>php2shell-scan/109618</code>, <code>php2shell-verify/1.0</code>, <code>Mozilla/5.0 (php2shell-poc)</code>.</li>
<li><strong>Requests:</strong> multipart POSTs to <code>/index.php</code> that upload two files named <code>a</code> and <code>b</code> through the upload-progress path; follow-up <code>GET</code> requests using <code>php://filter</code> to read a session file.</li>
<li><strong>Session files containing PHP code.</strong> The attempt VulnCheck saw tried to plant a webshell through a session file, with a payload that prints <code>PWNED::</code>. A legitimate PHP session file contains serialized data, never <code>&lt;?php</code>.</li>
</ul>
<p>Two checks you can run on a Linux host. We tested both against sample files; adjust paths to your log format and to the <code>session.save_path</code> of the pool that serves traffic (<code>php -i</code> shows the CLI&rsquo;s value, not necessarily FPM&rsquo;s):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Web logs: known scanner user agents and php://filter reads</span>
</span></span><span style="display:flex;"><span>grep -hE <span style="color:#e6db74">&#39;php2shell|php://filter&#39;</span> /var/log/nginx/access.log* /var/log/apache2/access.log* 2&gt;/dev/null
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Session files that contain PHP code or the test marker</span>
</span></span><span style="display:flex;"><span>grep -lE <span style="color:#e6db74">&#39;&lt;\?php|PWNED::&#39;</span> /var/lib/php/sessions/sess_* 2&gt;/dev/null
</span></span></code></pre></div><p>Then do the usual post-compromise checks for a web server: new or changed <code>.php</code> files under the document root since October 17, unexpected child processes of the PHP worker or web server user (shells, <code>curl</code>, <code>wget</code>), and outbound connections from web hosts. Our guide to <a href="/posts/logging-for-incidents-not-for-dashboards/">logging for incidents</a> covers which of these you will wish you had recorded.</p>
<p>Federal agencies have to follow CISA&rsquo;s forensic triage requirements for this KEV entry. If you want to borrow that process, our explainer on <a href="/posts/cisa-bod-26-04-explained-kev-deadlines-forensic-triage-and-what-private-teams-can-borrow/">CISA BOD 26-04</a> covers it.</p>
<h2 id="limits-of-this-article">Limits of this article</h2>
<p>We have not read the full GitHub security advisories, which PHP says contain the technical details; they were not reachable from our research environment. Exploitation reporting comes from vendors and press summaries we cite, not from our own telemetry. The hunting indicators come from one vendor&rsquo;s honeypots and will not catch a modified attack. Exposure counts published by vendors differ widely, so we have not repeated them.</p>
<h2 id="sources-and-verification">Sources and verification</h2>
<table>
  <thead>
      <tr>
          <th>Important claim</th>
          <th>Source</th>
          <th>Status</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Affected ranges 8.2 &lt; 8.2.35, 8.3 &lt; 8.3.36, 8.4 &lt; 8.4.27, 8.5 &lt; 8.5.12; mechanisms; CVSS v4.0 9.2 vector; CWEs; credits</td>
          <td><a href="https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/109xxx/CVE-2026-109618.json">CVE-2026-109618</a> and <a href="https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/109xxx/CVE-2026-109619.json">CVE-2026-109619</a> records (PHP CNA)</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>SAPIs at risk, mod_php highest, fixed releases, 8.1-and-older guidance, source backports, all stopgaps and their caveats</td>
          <td><a href="https://www.php.net/archive/2026.php">PHP security advisory, Oct 21, 2026</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Fix shipped in 8.2.35, 8.3.36, 8.4.27, 8.5.12 as &ldquo;Avoid state corruption via bailout&rdquo;</td>
          <td>PHP NEWS files for <a href="https://github.com/php/php-src/blob/php-8.4.27/NEWS">8.4.27</a> and the other tags</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Full FPM exploit not demonstrated at disclosure</td>
          <td><a href="https://openwall.com/lists/oss-security/2026/10/21/6">oss-security, Oct 21, 2026</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>KEV addition Oct 26, due Oct 29, forensic triage flag</td>
          <td><a href="https://github.com/cisagov/kev-data">CISA KEV catalog data</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Ubuntu 24.04 package 8.3.6-0ubuntu0.24.04.13 includes the fix</td>
          <td>Package changelog on an Ubuntu 24.04 host, inspected October 27, 2026</td>
          <td>Verified (one package)</td>
      </tr>
      <tr>
          <td>php_admin_value cannot be overridden with ini_set</td>
          <td><a href="https://www.php.net/manual/en/install.fpm.configuration.php">PHP-FPM configuration docs</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Exploitation attempt from Oct 17</td>
          <td>Amazon, as reported by <a href="https://infosecurity-magazine.com/news/php2shell-exploitation-attempt">Infosecurity Magazine</a></td>
          <td>Qualified (secondary report)</td>
      </tr>
      <tr>
          <td>Scanner user agents, request pattern, session-file webshell attempt</td>
          <td><a href="https://www.vulncheck.com/blog/php2shell-vulnerabilities">VulnCheck, Oct 21, 2026</a></td>
          <td>Qualified (one vendor&rsquo;s honeypots)</td>
      </tr>
      <tr>
          <td>No confirmed successful RCE as of Oct 23</td>
          <td><a href="https://securityaffairs.com/?p=201538">Security Affairs</a></td>
          <td>Qualified (secondary report)</td>
      </tr>
      <tr>
          <td>FBI: apply updates immediately</td>
          <td><a href="https://www.ic3.gov/PSA/2026/PSA261023">FBI IC3 PSA I-102326-PSA</a></td>
          <td>Verified</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item></channel></rss>