Research · 6 min read

ProfilePress Vulnerability: Why Shortcode Bugs Keep Coming Back

By WP Vanguard Team

ProfilePress Vulnerability: Why Shortcode Bugs Keep Coming Back

ProfilePress, the membership and user-profile plugin installed on 100,000+ WordPress sites, has a vulnerability that lets any logged-in subscriber read other users' email addresses, login names and registration dates. Tracked as CVE-2026-92536 and scored CVSS 8.8 by Wordfence, this ProfilePress vulnerability affects every version through 4.17.4. On sites that leave public registration open, an attacker doesn't need an account at all.

The fix shipped in 4.17.5 on September 21. The CVE went public on October 2, eleven days later. That gap matters if you update on a schedule rather than on advisories.

The bigger story is the pattern. Reading the changelog, ProfilePress has closed a shortcode hole in a different profile field in five releases since early August.

Key finding

Update to 4.17.6, not just 4.17.5. The newest release closes one more shortcode path and several other security holes that 4.17.5 leaves open.

What the ProfilePress Vulnerability Lets an Attacker Do

ProfilePress renders member directories and profile pages from templates that contain shortcodes. Fields like a user's nickname and biographical info end up inside that output.

Per the CVE record, an attacker stores crafted text in their own nickname and bio fields. When the Member Directory builds its listing, it rebinds each row to a different user. The attacker's stored [pp-custom-html] payload, encoded in base64, then runs against that other user's data and calls [profile-email], [profile-username] and [profile-date-registered]. The result is a page that prints someone else's details.

The unauthenticated route is the one to worry about. When users_can_register is on, the plugin's registration handler processes reg_nickname and reg_bio without a nonce check. A visitor can submit the payload there and never log in.

Email addresses and login names are the raw material for phishing and targeted password attacks. They aren't a takeover by themselves, but they remove two of the guesses an attacker would otherwise have to make.

Five Releases, Five Different Fields

Wordfence's advisory describes one bug. The plugin's changelog describes a run of them. Here's what each release says it fixed, with the release dates from the WordPress.org repository:

One shortcode fix per release
  1. 4.17.0Aug 5Shortcode execution on first and last name fields
  2. 4.17.1Aug 18Shortcode execution on frontend profile data
  3. 4.17.3Sep 5Security issue in the bio on the frontend profile
  4. 4.17.5Sep 21Nickname and bio exposure, CVE-2026-92536
  5. 4.17.6Oct 2Shortcode execution via comment content on a profile

An earlier one, CVE-2026-3309, hit billing field values at checkout in versions through 4.16.11. We covered it in our April vulnerability roundup when it had no patch.

Each fix closed one field. The next release found another field. That is what you'd expect when the defence is "strip shortcodes from this input" and the plugin has dozens of places where stored text reaches do_shortcode().

Why Stripping Shortcodes From Input Didn't Hold

The 4.17.5 code diff, which is public on WordPress.org, shows why the earlier fixes kept leaking. The comments in the patch spell out two bypasses.

First, strip_shortcodes() makes a single pass. A nested value like [profile-[profile-email]email] comes out of it as a working shortcode, so ProfilePress already looped the call until the value stopped changing.

Second, and harder to see: split fragments. One field can hold [pp-custom-html and another can hold the rest of the tag. Each value looks harmless alone. Once the plugin renders them and concatenates the results into one template buffer, a second do_shortcode() pass sees a complete shortcode and runs it.

Input filtering can't catch that, because the dangerous string doesn't exist until later.

How 4.17.5 Changed the Approach

The patch moves the defence to the output side. It adds a helper that replaces every [ and ] with the hex entities [ and ] before profile values are printed. Browsers show the same text, but do_shortcode() can't parse it.

The code comment explains the choice of hex: do_shortcode() runs unescape_invalid_shortcodes(), which turns the decimal entities [ and ] back into real brackets and would undo the fix.

A second helper cleans the assembled template buffers in the profile and Member Directory output before the outer do_shortcode() call. It disarms pp-custom-html tags, any [ that spans an HTML tag boundary, and any unterminated [. The patch also applies the encoding to the username, email and website tags, to custom profile fields, and to both profile and directory listing themes.

This is the right fix. Escaping at the sink holds even when a new field gets added later.

How to Check Your Site

Check the installed version first:

wp plugin get wp-user-avatar --field=version

Anything at 4.17.4 or earlier is exposed to this bug. Then see whether open registration turns it into an unauthenticated one:

wp option get users_can_register

A result of 1 means anyone can register, and the registration handler is reachable by visitors.

You can also look for stored payloads. This query lists accounts whose nickname or bio contains an opening bracket. Adjust wp_ if your table prefix differs:

wp db query "SELECT user_id, meta_key FROM wp_usermeta WHERE meta_key IN ('nickname','description') AND meta_value LIKE '%[%'"

Plenty of legitimate bios contain brackets, so treat a hit as a lead. A hit that also contains pp-custom-html is not a coincidence.

What to Do Right Now

Update to 4.17.6, not just 4.17.5:

wp plugin update wp-user-avatar

The newest release fixes one more shortcode path, and its changelog lists other security fixes too, including unauthenticated file upload through non-file custom fields and a registration form ID that could be tampered with to bypass invite codes, CAPTCHA and form-assigned roles. If you stopped at 4.17.5, you're missing those.

If you can't update today and you don't need open registration, switching it off removes the unauthenticated route.

We haven't seen reports of active exploitation of CVE-2026-92536 as of October 4, and our exploited-in-the-wild feed doesn't list it. A bug that prints user emails is easy to probe for, so we wouldn't treat that as a reason to wait.

The wider lesson applies to any plugin that renders user-supplied text through shortcodes: encode at output, and assume a field you haven't thought about is next. Our guide to checking plugins for known vulnerabilities covers how to catch these between advisories. The same stored-input-rendered-later pattern drives much of the unauthenticated stored XSS in WordPress plugins we track, and our look at shortcode attributes handed to file loaders shows the same root problem on a different sink.

Run a scan on your site to check your ProfilePress version against our vulnerability database.

References

profilepress-vulnerability cve-2026-92536 shortcode-injection information-exposure do-shortcode

Related reading

Check Your WordPress Site Security

Free scan, no login required. Find vulnerabilities before attackers do.

Scan Your Site Free

Get weekly WordPress security tips

Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.

WP Vanguard is built by Wbcom Designs, makers of Reign, Jetonomy, Listora, and more. Explore our WordPress products →
← Back to Blog