Skip to content
Witen field notes

WordPress 7.1.4: close the upgrade folder, then update

· Witen Labs · Security advisory

What happened

WordPress 7.1.4 came out on October 28, 2026 with twelve security fixes. One of them matters to every WordPress site: while a site installs a WordPress update, an attacker with no account could reach a second copy of the WordPress installer sitting in a folder anyone can browse, and use it to take the site over.

  • Who is affected: every site older than the fixed release on its branch that updates with WordPress’s own updater, which is nearly all of them.
  • The window is short, but every site opens it: the attack works only during the seconds WordPress spends unpacking an update, so an attacker has to ask for the installer again and again to land in it. Every site that updates opens that window.
  • The catch: updating to 7.1.4 runs the updater you have now, the vulnerable one. The update itself opens the window. Close the upgrade folder first, then update.
  • Ten of the other eleven fixes need an account on your site, mostly one that can write posts. They matter most on sites with several authors. The full list is below.

How the attack works

When WordPress installs an update, it unpacks the new version into a folder inside wp-content/upgrade/, then copies the files over your site. That folder is on your web server like everything else under wp-content, and before 7.1.4 three things went wrong:

  • Its name came straight from the update package, with nothing random added.
  • Its contents could be listed: the cleanup step deleted the empty index.php that stops a web server from showing a folder’s files.
  • The unpacked copy included the WordPress installer, wp-admin/setup-config.php, which runs without a configuration file. Anyone who reached it could point that copy of WordPress at a database of their own.

WordPress 7.1.4 adds 16 random characters to the folder name, keeps the index.php, and stops the updater from copying a wp-config.php out of the unpacked folder (the WordPress code change). That last fix tells you what an attacker aims for: a configuration file of their own, copied over yours, putting your site on their database and them in charge of it.

Step 1: Check your version

In your dashboard, go to Dashboard → Updates. It shows the version you run and whether a newer one is available. WordPress shipped the fix to every branch it still supports, so you don’t have to jump to 7.1 to get it.

WordPress releases that contain the 7.1.4 security fixes
Your branchFixed in
7.17.1.4
7.07.0.8
6.96.9.11
6.86.8.12
6.76.7.11
6.66.6.11
6.56.5.14
6.46.4.14
6.36.3.14
6.26.2.15
6.16.1.16
6.06.0.18
5.0 to 5.95.9.20, 5.8.19, 5.7.21, 5.6.23, 5.5.24, 5.4.25, 5.3.27, 5.2.30, 5.1.28, 5.0.31
4.7 to 4.94.9.35, 4.8.34, 4.7.39

Already on a fixed version? If background updates installed it for you, your site went through the window once. Skip to Step 3.

Older than 4.7? WordPress publishes no fix. Close the upgrade folder for good and plan a move to a supported version.

Step 2: Close the upgrade folder, then update

WordPress’s updater works on files directly, never through the web, so nothing a visitor needs lives in wp-content/upgrade/. Refuse every web request for it and the attack has nothing to reach. Add the rule for your web server, update WordPress, and leave the rule in place: it costs nothing and covers the next flaw in this folder too.

Don’t put the rule in a file inside wp-content/upgrade/: the updater you’re running now empties that folder at the start of every update.

Apache

Add this line to the .htaccess file in your site’s root folder, above the # BEGIN WordPress line so WordPress never rewrites it:

RedirectMatch 403 ^/wp-content/upgrade(/|$)

nginx

Add these two lines inside your site’s server block, then run nginx -t and reload nginx. The ^~ makes nginx stop here before any .php rule, so the installer never reaches PHP:

location ^~ /wp-content/upgrade/ { deny all; }
location = /wp-content/upgrade { deny all; }

Caddy

Add these two lines inside your site’s block, then reload Caddy:

@wpupgrade path /wp-content/upgrade /wp-content/upgrade/*
respond @wpupgrade 403

Then check it

Open https://your-site.example/wp-content/upgrade/ in a browser. You should see 403 Forbidden. Your pages, images, and uploads keep working.

On managed hosting with no access to server settings? Ask your host whether /wp-content/upgrade/ is reachable from the web, and to block it if so. Then update.

Step 3: Check nobody got in

The attack leaves a trail in your web server’s access log: requests for files inside wp-content/upgrade/. Search for them, adjusting the path to wherever your host keeps logs:

grep -h "/wp-content/upgrade/" /var/log/apache2/access.log* /var/log/nginx/access.log* 2>/dev/null

A request for the folder itself answered with 403 or 404 is someone looking. A request for a .php file inside it answered with 200 is someone who got through. If you find one:

  • Check wp-config.php. Its DB_HOST, DB_NAME, and DB_USER should be the database you set up. A changed file date or an unfamiliar database means the site is no longer yours.
  • Look under Users → All Users for administrators you didn’t create.
  • Look in wp-content/upgrade/ for anything left behind. After an update finishes it should hold nothing but an index.php.
  • If anything is wrong, take the site offline, restore from a backup made before the update, change every password and secret key, and update before you put it back.

What we saw on our sensors

We searched every request the WordPress sites and servers that report to Witen have flagged since October 1. Nothing has reached for an unpacked installer. Three requests asked for the wp-content/upgrade/ folder itself, all from Microsoft Azure addresses and all refused. One came the day before the release, so it reads as an ordinary scan for folders that list their files, not as this attack. Requests for the main WordPress installer, the classic hunt for sites left half-installed, go back weeks and have nothing to do with 7.1.4.

Our sensors are a small slice of the web, so silence there doesn’t mean nobody is trying. It means the attack is aimed at the moment of an update, and most of the time, no update is running.

The other fixes in 7.1.4

Every other fix needs an account on your site, except one: a Customizer preview request could show an anonymous visitor theme changes someone had saved but not yet published. 7.1.4 shows those unpublished changes only to users allowed to use the Customizer.

The rest close holes that let a logged-in user plant script that runs in someone else’s browser (stored cross-site scripting), usually aimed at an administrator:

  • Specially crafted block markup
  • Privacy data removal requests
  • The Interactivity API, which also had a way to break pages for every visitor
  • Customizer selective refresh
  • The Categories, Playlist, image, and pagination blocks
  • Specially crafted usernames

One more lets privileged users read Notes on posts they can’t edit. 7.1.4 also updates WordPress’s bundled root certificates following the revocation of eMudhra.

Sources