<?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>Rce | FirewallSync</title><link>https://firewallsync.com/tags/rce/</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>Wed, 04 Nov 2026 04:40:00 +0000</lastBuildDate><atom:link href="https://firewallsync.com/tags/rce/index.xml" rel="self" type="application/rss+xml"/><item><title>WordPress CVE-2026-119977: Patch the Upgrade Race RCE</title><link>https://firewallsync.com/posts/wordpress-cve-2026-119977-upgrade-race-rce-kev/</link><guid>https://firewallsync.com/posts/wordpress-cve-2026-119977-upgrade-race-rce-kev/</guid><pubDate>Wed, 04 Nov 2026 04:40:00 +0000</pubDate><dc:creator>John Marshall</dc:creator><category>Security Operations</category><description>CISA added CVE-2026-119977 to the KEV catalog on 3 November 2026. In WordPress 4.7 through 7.1.3, a full-package core update stages a copy of WordPress, installer included, in a web-served folder under wp-content/upgrade, and an unauthenticated attacker who reaches it during the update window can run code. Here are the fixed versions per branch, what the 7.1.4 code change does, why the update itself is a risky moment, and what to check afterwards.</description><enclosure url="https://firewallsync.com/posts/wordpress-cve-2026-119977-upgrade-race-rce-kev/cover_hu7098877180882857123.jpg" type="image/jpeg" length="0"/><media:content url="https://firewallsync.com/posts/wordpress-cve-2026-119977-upgrade-race-rce-kev/cover_hu7098877180882857123.jpg" medium="image" type="image/jpeg" width="1200" height="630"/><content:encoded><![CDATA[<p><img src="https://firewallsync.com/posts/wordpress-cve-2026-119977-upgrade-race-rce-kev/cover_hu7098877180882857123.jpg" alt="Looking up at steel scaffolding tubes, clamps and wooden boards fixed to the side of a brick building under construction" width="1200" height="630"></p><p><strong>Scope.</strong> This post is based on the CVE record published by Wordfence (the CNA), the CISA KEV entry and CISA&rsquo;s SSVC assessment, the WordPress 7.1.4 release notes, and a diff we ran of the WordPress 7.1.3 and 7.1.4 source files. The exploitation telemetry is Wordfence&rsquo;s, as reported by The Hacker News. We did not reproduce the attack.</p>
<h2 id="what-the-vulnerability-is">What the vulnerability is</h2>
<p>The CVE record&rsquo;s description says: &ldquo;WordPress Core is vulnerable to Remote Code Execution in versions 4.7 through 7.1.3. This is due to predictable, web-accessible staging paths used during full-package core upgrades. This makes it possible for unauthenticated attackers to execute code on the server during the upgrade window.&rdquo;</p>
<table>
  <thead>
      <tr>
          <th>Field</th>
          <th>Value</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CVE</td>
          <td>CVE-2026-119977</td>
      </tr>
      <tr>
          <td>CNA</td>
          <td>Wordfence (published 31 October 2026)</td>
      </tr>
      <tr>
          <td>Weakness</td>
          <td>CWE-367, Time-of-check Time-of-use (TOCTOU) race condition</td>
      </tr>
      <tr>
          <td>CVSS 3.1</td>
          <td>8.1 High, <code>AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H</code></td>
      </tr>
      <tr>
          <td>Reporter</td>
          <td>Umut Bayram</td>
      </tr>
      <tr>
          <td>KEV</td>
          <td>Added 3 November 2026; due 6 November 2026; ransomware use Unknown; forensic triage: Yes</td>
      </tr>
      <tr>
          <td>CISA SSVC</td>
          <td>Exploitation active, Automatable no, Technical Impact total</td>
      </tr>
  </tbody>
</table>
<p>The attack complexity is High for a reason: the attacker has to hit files that exist only while a core update runs. According to The Hacker News&rsquo;s summary of Wordfence&rsquo;s analysis, exploitation needs a full-package update that includes the installer files, public web and PHP access to the staging tree, a predictable or discovered staging path, and enough time before WordPress deletes the temporary files. The same report says attackers have been repeatedly polling paths such as <code>setup-config.php</code>.</p>
<p>&ldquo;Automatable: no&rdquo; in the SSVC entry does not make this low priority. It reflects the narrow timing window, not the impact. Combined with active exploitation and total technical impact, it still puts the CVE near the top of a queue; <a href="/posts/cisa-vulnrichment-how-to-read-ssvc-values-in-a-cve-record-and-turn-them-into-a-patch-decision/">our SSVC guide</a> shows how your own mission and exposure values turn those three into a decision, and every public WordPress site is internet-facing.</p>
<h2 id="fixed-versions">Fixed versions</h2>
<p>WordPress released 7.1.4 on 28 October 2026 and says: &ldquo;Because this is a security release, it is recommended that you update your sites immediately.&rdquo; The release fixes this issue (&ldquo;A race condition during core updates that could lead to remote code execution reported by Umut Bayram&rdquo;) along with 21 other listed items.</p>
<p>The CVE record lists 25 affected branches, each with an inclusive upper limit (<code>lessThanOrEqual</code>). We checked each against the backport list in the release notes; in every branch the fixed release is the next point release.</p>
<table>
  <thead>
      <tr>
          <th>Branch</th>
          <th>Last affected</th>
          <th>Fixed</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>7.1</td>
          <td>7.1.3</td>
          <td><strong>7.1.4</strong></td>
      </tr>
      <tr>
          <td>7.0</td>
          <td>7.0.7</td>
          <td>7.0.8</td>
      </tr>
      <tr>
          <td>6.9</td>
          <td>6.9.10</td>
          <td>6.9.11</td>
      </tr>
      <tr>
          <td>6.8</td>
          <td>6.8.11</td>
          <td>6.8.12</td>
      </tr>
      <tr>
          <td>6.7</td>
          <td>6.7.10</td>
          <td>6.7.11</td>
      </tr>
      <tr>
          <td>6.6</td>
          <td>6.6.10</td>
          <td>6.6.11</td>
      </tr>
      <tr>
          <td>6.5</td>
          <td>6.5.13</td>
          <td>6.5.14</td>
      </tr>
      <tr>
          <td>6.4</td>
          <td>6.4.13</td>
          <td>6.4.14</td>
      </tr>
      <tr>
          <td>6.3</td>
          <td>6.3.13</td>
          <td>6.3.14</td>
      </tr>
      <tr>
          <td>6.2</td>
          <td>6.2.14</td>
          <td>6.2.15</td>
      </tr>
      <tr>
          <td>6.1</td>
          <td>6.1.15</td>
          <td>6.1.16</td>
      </tr>
      <tr>
          <td>6.0</td>
          <td>6.0.17</td>
          <td>6.0.18</td>
      </tr>
      <tr>
          <td>5.0 to 5.9</td>
          <td>5.0.30 &hellip; 5.9.19</td>
          <td>5.0.31, 5.1.28, 5.2.30, 5.3.27, 5.4.25, 5.5.24, 5.6.23, 5.7.21, 5.8.19, 5.9.20</td>
      </tr>
      <tr>
          <td>4.7 to 4.9</td>
          <td>4.7.38, 4.8.33, 4.9.34</td>
          <td>4.7.39, 4.8.34, 4.9.35</td>
      </tr>
  </tbody>
</table>
<p>WordPress adds that backports are &ldquo;a courtesy&rdquo; and that &ldquo;only the most recent version of WordPress is actively supported.&rdquo; Sites on 4.6 or earlier get no fix at all.</p>
<h2 id="what-changed-in-714">What changed in 7.1.4</h2>
<p>We fetched <code>wp-admin/includes/class-wp-upgrader.php</code> and <code>wp-admin/includes/update-core.php</code> from the 7.1.3 and 7.1.4 tags of the WordPress/WordPress GitHub mirror and diffed them. Three changes stand out.</p>
<ol>
<li><strong>The staging folder name becomes unguessable.</strong> In 7.1.3, <code>unpack_package()</code> names the working directory after the downloaded package file: <code>$upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' )</code>, inside <code>wp-content/upgrade/</code>. In 7.1.4 a new <code>get_working_dir_name()</code> appends <code>'-' . wp_generate_password( 16, false )</code>.</li>
<li><strong>The upgrade folder can no longer be listed.</strong> 7.1.3 deletes everything in <code>wp-content/upgrade/</code> before unpacking. 7.1.4 skips <code>index.php</code> during that cleanup and writes one if missing, with a comment that the directory &ldquo;is web-served&rdquo; and must not be listed &ldquo;so the name of the working directory created below cannot be discovered from a directory index.&rdquo;</li>
<li><strong>A staged wp-config.php is never copied into the live site.</strong> <code>update_core()</code> in 7.1.4 adds <code>wp-config.php</code> to the list of files it skips when copying the new release over the old one, with the comment &ldquo;Never copy a wp-config.php, which could have been written to the working directory.&rdquo;</li>
</ol>
<p>Read together, the fix closes both halves of the race: finding the staged copy, and turning a file written into it into something that persists after the update. That is our reading of the diff; the CNA&rsquo;s own advisory is the authority on the exploit chain.</p>
<h2 id="why-the-update-itself-is-the-risky-moment">Why the update itself is the risky moment</h2>
<p>The vulnerable step runs in the code that is already installed. When WordPress updates core, <code>Core_Upgrader::upgrade()</code> calls <code>unpack_package()</code> from the running version&rsquo;s <code>WP_Upgrader</code> class, and only then copies the new release&rsquo;s <code>update-core.php</code> into place and runs it. So updating a 7.1.3 site to 7.1.4 stages the 7.1.4 package with the 7.1.3 naming and cleanup logic. The new wp-config.php skip does apply during that update, because it lives in the new <code>update-core.php</code>, but the staging folder is still predictable and listable for that one run.</p>
<p>Two practical consequences:</p>
<ul>
<li><strong>Block the staging path before you update</strong>, not after. A web server rule that refuses every request under <code>/wp-content/upgrade/</code> removes the public half of the race. WordPress writes to that folder through the filesystem, not over HTTP, so it should not need web access to it.</li>
<li><strong>Do not rely on a rule file inside <code>wp-content/upgrade/</code>.</strong> Affected versions delete everything in that folder before unpacking, so a <code>.htaccess</code> placed there is gone when it matters.</li>
</ul>
<p>Illustrative configuration (we did not test these against a live site; adapt paths for subdirectory installs):</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:#75715e"># nginx, inside the WordPress server block
</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">/wp-content/upgrade/</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><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-apache" data-lang="apache"><span style="display:flex;"><span><span style="color:#75715e"># Apache, in the site&#39;s root .htaccess or vhost (mod_alias)</span>
</span></span><span style="display:flex;"><span>RedirectMatch <span style="color:#ae81ff">403</span> ^/wp-content/upgrade/
</span></span></code></pre></div><p>Also check whether automatic updates already did the work. In 7.1.4&rsquo;s <code>Core_Upgrader::should_update_to_version()</code>, the minor auto-update setting reads <code>get_site_option( 'auto_update_core_minor', 'enabled' )</code>, so minor (security) releases install automatically unless the <code>WP_AUTO_UPDATE_CORE</code> constant, a filter or that option turns them off. Many sites will have moved to their branch&rsquo;s fix on their own; managed hosts and fleets that disable auto-updates will not have.</p>
<h2 id="what-to-do-this-week">What to do this week</h2>
<ol>
<li><strong>Inventory versions.</strong> On each site, <code>wp core version</code> (WP-CLI) or <code>wp-includes/version.php</code> gives <code>$wp_version</code>. Anything at or below its branch&rsquo;s &ldquo;last affected&rdquo; row above needs the update. Anything on 4.6 or earlier needs a migration plan.</li>
<li><strong>Block <code>/wp-content/upgrade/</code> at the web server</strong>, reload, and confirm with a request that it returns 403.</li>
<li><strong>Update to 7.1.4</strong>, or to your branch&rsquo;s fixed release if you cannot move to 7.1 yet.</li>
<li><strong>Check for leftovers.</strong> CISA marks this entry for forensic triage. At minimum:</li>
</ol>
<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"># Run from the WordPress root. Illustrative; adapt the log path.</span>
</span></span><span style="display:flex;"><span>wp core verify-checksums                 <span style="color:#75715e"># core files that differ from the release</span>
</span></span><span style="display:flex;"><span>ls -la wp-content/upgrade/               <span style="color:#75715e"># should be empty apart from index.php after 7.1.4</span>
</span></span><span style="display:flex;"><span>find . -name <span style="color:#e6db74">&#39;wp-config.php&#39;</span> -not -path <span style="color:#e6db74">&#39;./wp-config.php&#39;</span>   <span style="color:#75715e"># unexpected copies</span>
</span></span><span style="display:flex;"><span>grep -E <span style="color:#e6db74">&#39;/wp-content/upgrade/&#39;</span> /var/log/nginx/access.log* | grep -v <span style="color:#e6db74">&#39; 403 &#39;</span>
</span></span></code></pre></div><p>Requests to <code>/wp-content/upgrade/.../setup-config.php</code> or <code>install.php</code> that did not get a 403, especially close to the time of a core update, are the lead to follow. Look for PHP files that <code>verify-checksums</code> does not explain, new administrator accounts, and changes to <code>wp-config.php</code> since the update.</p>
<ol start="5">
<li><strong>Record the decision.</strong> If you track patch decisions as tickets, this is a KEV entry with active exploitation and total technical impact on internet-facing hosts; our <a href="/posts/vulnerability-prioritization-workflow-cve-record-to-patch-ticket/">vulnerability prioritization workflow</a> shows how to carry those signals into the ticket, and <a href="/posts/cisa-kev-json-feed-what-each-field-means-and-how-to-match-it-against-a-scanner-export/">the KEV JSON feed guide</a> explains the <code>dueDate</code> and <code>forensicTriage</code> fields.</li>
</ol>
<h2 id="limits-of-this-article">Limits of this article</h2>
<ul>
<li>We did not reproduce exploitation. The preconditions and the 62,969-attack figure come from Wordfence via The Hacker News; we could not retrieve Wordfence&rsquo;s own advisory page in this run.</li>
<li>Which update package a given site downloads (full, no-content or partial) depends on what the WordPress update API offers it; we did not test which update paths stage the installer files.</li>
<li>The web server rules are illustrative and untested; test them on a staging site first.</li>
</ul>
<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>Description, affected ranges, CVSS 8.1, CWE-367, reporter, published date</td>
          <td><a href="https://github.com/CVEProject/cvelistV5/blob/main/cves/2026/119xxx/CVE-2026-119977.json">CVE-2026-119977 record (cvelistV5)</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>KEV added 3 Nov 2026, due 6 Nov 2026, forensic triage Yes</td>
          <td><a href="https://www.cisa.gov/known-exploited-vulnerabilities-catalog">CISA KEV catalog</a> (kev-data JSON, catalog 2026.11.03)</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>SSVC active / no / total</td>
          <td>CISA-ADP container in the CVE record</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>7.1.4 release date, fix description, backport versions, support statement</td>
          <td><a href="https://wordpress.org/documentation/?p=16371315">WordPress 7.1.4 release notes</a></td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Fixed release = next point release in all 25 branches</td>
          <td>CVE record vs release notes, our script</td>
          <td>Verified (computed)</td>
      </tr>
      <tr>
          <td>7.1.4 code changes; update runs old staging code</td>
          <td><a href="https://github.com/WordPress/WordPress/tree/7.1.3">WordPress 7.1.3</a> and <a href="https://github.com/WordPress/WordPress/tree/7.1.4">7.1.4</a> source, our diff</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>Minor auto-updates on by default</td>
          <td><code>wp-admin/includes/class-core-upgrader.php</code> (7.1.4)</td>
          <td>Verified</td>
      </tr>
      <tr>
          <td>62,969 blocked attacks in 24 hours; exploitation preconditions</td>
          <td><a href="https://thehackernews.com/2026/10/wordpress-rce-flaw-draws-nearly-63000.html">The Hacker News, 30 Oct 2026</a>, citing Wordfence</td>
          <td>Qualified (press report of vendor telemetry)</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item></channel></rss>