← Back to blog
· by The Wordify Team · in WordPress News

WordPress 7.1.1: eleven security fixes, and ten of them need a login

WordPress security release: WordPress 7.1.1. Eleven security fixes, one of which needs no account.

WordPress 7.1.1 landed on September 17, 2026. It fixes 11 security issues, and unlike 7.0.3 and 7.0.4 it is not security-only: there are 17 bug fixes in core alongside them. WordPress recommends updating immediately, which is the standard line for a security release and is the right advice.

The part worth ten minutes is the shape of the eleven. Exactly one of them can be reached by someone with no account on your site. The other ten need a login, and most need a login that can already write something. That is the cut that tells you whether this is a today job or a this-week job.

What shipped

The release was led by Adam Silverstein, Adrian Duffell, Andrei Draganescu and Aaron Jorbin. It is the first minor in the 7.1 branch, and it carries the cleanup for the features 7.1 "Mary Lou" shipped in August as well as the security work.

Between the 7.1.0 and 7.1.1 tags there are 33 commits, 48 files changed, 1,632 insertions and 139 deletions. Close to 880 of those insertions are new test coverage across eight test files, which is a large share for a minor release. WordPress lists 13 files as revised, and that list is the security surface.

One inconsistency if you are counting: the announcement says 19 bug fixes for the Block Editor and the version documentation says 21. The core figure of 17 and the security figure of 11 match in both.

The one that needs no account

Stored cross-site scripting through wpautop(), reported by Rafie Muhammad of Awesome Motive. WordPress describes it as injectable by an unauthenticated visitor, subject to comment approval.

wpautop() is the function that turns line breaks into paragraphs. One of its tidy-up passes moves a <p> that wraps a <blockquote> inside the blockquote instead, and to do that it has to work out where the <blockquote> tag ends. The old pattern found the end by looking for the first >. A > can legitimately sit inside a quoted attribute value, so the pattern could stop short and relocate the paragraph into the middle of an attribute rather than after the tag.

The fix is a single line. The new pattern understands quoting: it steps over "..." and '...' and only treats a > outside quotes as the end of the tag.

The reason a visitor can reach it is that wpautop() is attached to comment_text by default, not just to post content. The reason it is "subject to comment approval" is that an unapproved comment is not rendered to anyone. So the path has two steps: someone submits a crafted comment, and then somebody approves it. If your site auto-approves comments from previously approved authors, or has moderation switched off, that is one step rather than two.

The other ten, sorted by what the attacker needs

WordPress labels some of these with the account level required and leaves others unstated. Where it is unstated, the description below is what the patched code now checks.

A Contributor account is enough

  • Arbitrary post overwrite. _wp_translate_postdata() accepted a raw ID field on the create path, where the per-post capability checks do not run, because they only run on the update path. The fix rejects an ID on the create path outright, on the reasoning that legitimate post creation never carries one. Reported by Anthropic.
  • Draft and pending post slug disclosure. wp_ajax_sample_permalink() built a permalink for whatever post ID it was handed, behind a nonce check and nothing else. The fix adds a current_user_can( 'edit_post', $post_id ) check, and the same check to wp_ajax_get_permalink() alongside it. Reported by hermanhms.

Any authenticated account

  • Comments and notes could be reparented onto any post. The REST comments controller checked that you were allowed to edit a comment where it currently sat. It did not check the post you were moving it to. So a user who could edit their own comment or note could attach it to a post they could neither read nor edit. The fix adds a check_target_post_permission() helper and runs it at both ends of the move. Reported by viridis.
  • A private parent post's title leaked through the attachment screen. The "Uploaded to" line on an attachment's edit screen printed the parent post's title without checking whether the current user could read that post. The fix is one added current_user_can( 'read_post', ... ). Reported by HDWSec.

An account that already holds real privileges

  • Path traversal in the REST templates controller. _get_block_template_file() assembled a file path from a slug and checked only that the file existed. The fix resolves both the target file and the template directory with realpath() and rejects anything that does not sit underneath the template directory. Reported by Anthropic.
  • Custom CSS capability bypass over XML-RPC. customize_changeset posts could be written through the generic XML-RPC post API, which does not enforce the edit_css check the Customizer path does. The fix rejects XML-RPC writes to internal-only builtin post types, with a new xmlrpc_allow_post_type_writes filter for anyone who needs to opt one back in. Reported by Ben Bidner of the WordPress Security Team.
  • Stored XSS through custom header images. Themes that support custom headers store the header image data as a theme mod, and that value was not sanitised on the way in. This is the largest patch in the release: roughly 170 new lines adding a sanitize() method that assembles the value member by member from a known set of keys, rather than filtering the supplied one, so nothing else can survive. get_custom_header() now also casts width and height through absint(). Reported by Jeremy Felt of the WordPress Security Team.
  • HTML API comment breakout. set_modifiable_text() already refused text that could close an HTML comment, but its pattern missed the abrupt-closing forms. One character class added. Reported by Jeremy Felt.
  • Theme install and preview from a crafted URL. The theme installer took a slug from the URL and dropped it straight into a jQuery selector, so a crafted URL could install and preview an inactive theme from WordPress.org. The fix runs the slug through $.escapeSelector() and scopes the selector to div.theme. Reported by Paulos Yibelo and pwn.ai.
  • Multisite network activation of a network-only plugin. A site administrator could Ajax-activate a plugin marked network-only, which activates it across the whole network. Two changes: the Ajax handler now requires manage_network_plugins, and is_network_only_plugin() normalises the plugin path the same way activate_plugin() does, so the two cannot be made to disagree about which file is being activated. Reported by Jesse McNeil.

Our read, and this is opinion rather than anything WordPress has said: there is a theme running through most of this list. Two code paths that should agree about the same thing were checking different things, or checking at only one end. The create path trusting a field the update path validates. A comment authorised where it is but not where it is going. A plugin path resolved one way by the activator and another way by the network check. None of these are exotic. They are the kind of gap that opens up when a feature grows a second entry point.

Two of the eleven were reported by Anthropic

The arbitrary post overwrite and the REST path traversal are both credited to Anthropic, the AI company, in the release announcement and the version documentation.

Both are logic flaws of a particular kind: they need someone to hold two distant pieces of code in mind at once and notice they disagree. That is tedious work for a human reviewer and well suited to a machine that can read the whole file tree.

Our read, again opinion: the consequence for site owners is not about who found them. It is that the review capacity pointed at core is going up, so expect more releases that clear out a batch of old, quiet logic bugs. That is a good thing that will look like a busier update calendar.

There are no CVEs on this one, at least not yet

7.0.3 and 7.0.4 each carried one CVE with a CVSS score attached. At the time of writing, none of these 11 has a CVE published in the WordPress project's GitHub advisory database.

That is not a statement about severity. WordPress does not assign a CVE to everything it fixes, and the ones that do get assigned often appear days or weeks after the release. What it means practically is that there is no score to triage by, so the vector, meaning what an attacker has to already hold, is the only useful sorting tool for this release. That is what the section above is for.

"I'm not on WordPress 7.1. Am I patched?"

Yes, as long as you take the update. You do not need a major version upgrade to get patched.

The announcement said backports were "in progress and will ship as they become ready", which reads like a change from 7.0.3 and 7.0.4, where every branch shipped the same day. In practice they all landed the same day here too: every branch back to 4.7 was tagged on September 17, and the WordPress version API now reports a patched release for each of them.

Your branch Affected by Update to
7.1 11 of 11 7.1.1
7.0 11 of 11 7.0.5
6.9 11 of 11 6.9.8
6.8 11 of 11 6.8.9
6.7 11 of 11 6.7.8
6.6 10 of 11 6.6.8
6.5 10 of 11 6.5.11
6.4 10 of 11 6.4.11
6.3 10 of 11 6.3.11
6.2 10 of 11 6.2.12
6.1 10 of 11 6.1.13
6.0 10 of 11 6.0.15
5.9 10 of 11 5.9.17
5.8 9 of 11 5.8.16
5.7 9 of 11 5.7.18
5.6 9 of 11 5.6.20
5.5 8 of 11 5.5.21
5.4 8 of 11 5.4.22
5.3 8 of 11 5.3.24
5.2 7 of 11 5.2.27
5.1 7 of 11 5.1.25
5.0 7 of 11 5.0.28
4.9 7 of 11 4.9.32
4.8 7 of 11 4.8.31
4.7 6 of 11 4.7.36
4.6 and earlier No longer receives security updates Upgrade

WordPress is clear that only the most recent version is actively supported. The backports are a courtesy, not a support commitment.

"10 of 11" is not one hole left open

If you are on 6.6, the documentation says your branch is affected by 10 of the 11 and that 6.6.8 fixes them. That does not leave one unpatched. The eleventh does not exist in your branch, because the code it lives in does not either.

You can read the exact cutoffs off the backport commits:

  • 11 to 10, at 6.6. set_modifiable_text() was added to the HTML API in 6.7.0. Branches older than that do not have the method, so they do not have the bug.
  • 10 to 9, at 5.8. _get_block_template_file() arrived with block templates in 5.9.0.
  • 9 to 8, at 5.5. The attachment screen only started printing the parent post's title in 5.6, so there is nothing to leak in 5.5 and earlier.
  • 8 to 7, at 5.2. The REST comments fix was not backported below 5.3.
  • 7 to 6, at 4.7. 4.7 also drops the theme installer fix.

Patched for your branch is full coverage. What it is not is a reason to stay on 5.5.

The maintenance half is the part you might actually notice

This is the real difference from 7.0.3 and 7.0.4, which were security-only. This one fixes bugs too, and several are 7.1 regressions. Four are worth knowing about:

  • Sitemaps returned a 404 on sites with no published posts. The sitemap itself was complete and valid, but it was served under a 404 status, and search engines discard that. If you launched a site on 7.1 and its sitemap has not been picked up, this is a plausible reason.
  • A PHP fatal in the new admin tooltips when the tooltip's HTML contained a % character, which sprintf() read as a placeholder.
  • Hook and widget registration could break when object IDs became integer array keys, a regression from a performance change that swapped spl_object_hash() for spl_object_id().
  • Front-end performance on 7.1's interactive states. The block states support resolved the block type and did a global styles lookup once per block on every front-end request, before it could establish that the block had no state styles at all. 7.1 shipped the feature; 7.1.1 makes it cheap.

When 7.1 shipped we said to treat a feature release as a deliberate, staged cutover rather than an overnight auto-update. A month on, that list is a decent argument for it.

What to do

  1. Check your version. In WP Admin, go to Dashboard, then Updates. The version you are on is at the top.
  2. Take the update. Sites with automatic background updates have most likely started already.
  3. Look at who holds an account, not just who holds admin. Contributor is enough for two of these, and any logged-in user is enough for two more. On most sites the useful question is not "who are my administrators" but "how many accounts exist that nobody has looked at in a year".
  4. If you allow comments, check your moderation settings. The only issue here that a stranger can reach depends on a comment being approved. Auto-approving previously approved commenters is a convenience with a cost attached.
  5. If you run multisite, the network-only plugin issue is specifically yours. Single-site installs are not affected by that one.
  6. Include staging and development copies. A forgotten but publicly reachable staging site carries the same exposure as the live one, and it is the copy nobody is watching.

If you are on Wordify, most of this has already happened

Automated Safe Updates treats a security release differently from a routine one. Routine updates wait for your update window. A release that closes a known vulnerability does not: it goes out as soon as it is available.

WordPress flags this for us directly. Its version API now reports the 7.1 branch as insecure, while the current patch on every other branch reads outdated. That difference is the signal, and it means 7.1.1 was fast-tracked for every eligible site rather than held for the small hours. The first sites were on the patched version within hours of the release, and the rest of the fleet followed.

Two details are worth pulling out, because they answer the two questions this post spends most of its length on.

  • Sites on older branches got their branch's backport, not a major upgrade. A site on 7.0 went to 7.0.5. A site on 6.9 went to 6.9.8. That is what the core setting "Minor & security only" does in practice, and it is why "am I patched" and "am I on the current major" are separate questions with separate answers.
  • Nothing was applied without a way back. Every site gets a verified restore point before the update. Afterwards Wordify loads the site and compares what comes back against what came back before, so a page that has broken or gone missing is caught. If it fails, the update is rolled back on its own and that release is put on hold.

Some sites always need a look by hand, and those land on your Tasks page rather than sitting silently. But for a release like this one the default outcome is that you read about it afterwards instead of working through it.

Automated Safe Updates is on every plan at no extra cost. Here is how it works.

Common questions

Is WordPress 7.1.1 urgent?

Update this week on any site. Update today if you have accounts you do not fully control, which means multi-author publications, membership or community sites, client sites where staff hold Contributor or Author logins, and anything with open registration. On a single-user site with comments closed, ten of the eleven are not reachable and the eleventh has nowhere to land. WordPress has published no evidence of exploitation in the wild and no proof of concept.

Will WordPress update itself?

Sites that support automatic background updates will pick up a minor release on their own, usually within hours. That is the design: minor releases land in-branch precisely so they can be applied without anyone reading an advisory first. Worth confirming rather than assuming, especially on sites where a plugin or a constant has switched auto-updates off.

There is no CVE. Does that mean it is minor?

No. It means no CVE has been published yet. WordPress does not assign one to every issue, and assignment often trails the release. Judge this release on what each issue needs from an attacker, not on whether it has an identifier.

I do not allow comments. Am I exposed to the wpautop() issue?

Not through the comment path, which is the one that makes it reachable without an account. Take the update regardless. wpautop() runs on post content and excerpts as well, so the underlying parsing bug is not comment-specific, and "comments are off" is a fact about today's settings.

I'm the only user on my site. Do I still need to update?

Ten of the eleven need an account and you are the only one who has one, so realistically you are not exploitable through them. Update anyway. "I'm the only user" is a statement about today, and the update costs you nothing.

Does this affect plugins or themes?

No. This is a WordPress core release. Plugin and theme vulnerabilities are tracked and patched on their own schedules, which is why keeping core current is necessary but never sufficient. The Stripe for WooCommerce 10.8.5 release is a good example of the separate track.

Should I be more careful because this is also a maintenance release?

Slightly, in the sense that a maintenance release changes behaviour and a security-only one mostly does not. In practice a minor release is still designed to be safe to apply in-branch, and the bugs being fixed here are ones you would rather not keep. If you run sites where an update breaking something is genuinely expensive, this is the release to put through staging first rather than the security-only ones that preceded it.

The unglamorous point

Eleven issues in one release reads badly until you look at what they are. Most are old, quiet gaps in code paths that grew a second entry point over the years, found by people who went looking. Finding them is the good outcome. Shipping them all at once with a full set of backports across 24 branches on the same day is the system working.

What quietly fails is the other half: whether the update actually reaches your sites. Auto-updates switched off during a debugging session two years ago. A staging copy nobody remembers. A site where an update broke something once, so updates got disabled and never re-enabled. We have written before about how little time there is between disclosure and exploitation, and the gap that matters is almost never the one between the patch shipping and you reading about it.

That gap is the whole reason we built Automated Safe Updates the way we did. A minor security release should be something you read about later, not something you work through.

If you are not sure whether your sites are on a patched version, talk to us and we will check with you.

More on this

Sources