A contributor with a pen writes JavaScript into a widget and it fires when anyone loads the page
JetWidgets For Elementor is a free widget pack for the Elementor page builder on WordPress. Versions up to and including 1.0.21 fail to properly sanitize and/or escape one or more widget attributes before rendering them, allowing a user with Contributor privileges or higher to inject arbitrary JavaScript that executes in the browser of any visitor who later loads the affected page. This is a classic stored XSS via authenticated post/widget input — the plugin trusts what an editorial user types into a shortcode/widget attribute and echoes it back into the DOM.
The vendor's 6.4 MEDIUM rating is accurate. CVSS scope-change (S:C) reflects that the payload runs in the site visitor's browser context, not the plugin's, and PR:L correctly captures the Contributor requirement. This is not a preauth site takeover — but it is also not zero. On a multi-author blog or membership site where Contributor is a self-service role, this is a real path to session theft against editors and admins.
4 steps from start to impact.
Acquire a Contributor-or-higher account
edit_posts capability, which maps to Contributor on default WordPress. They either register on a site that allows open registration with elevated default role, compromise a low-privileged editorial account via credential stuffing, or already hold a legitimate account on a multi-author site.- Site permits Contributor+ account creation OR attacker has stolen creds
- JetWidgets For Elementor ≤ 1.0.21 installed and active
- Most production WP sites do not grant Contributor by default registration
- MFA plugins (Wordfence Login Security, miniOrange) block cred-stuffing
wp-login.php brute activityCraft malicious widget payload
jet-animated-box, jet-price-list, etc.) and injects JavaScript into an unsanitized attribute — commonly a URL, onerror, or freeform text field. Tools: browser + Elementor UI, or direct REST API calls to /wp-json/wp/v2/posts with the shortcode body embedded.- Elementor active
- Contributor can save/preview drafts with the vulnerable widget
- Some deployments restrict Contributors from using Elementor entirely
- WAF rules (Wordfence, Sucuri, Cloudflare OWASP) flag
<script>in post bodies
Trigger execution against a privileged viewer
- Editor/Admin previews the malicious content, OR post reaches public URL
- Draft-only workflows mean payload only fires on internal reviewer, not public users
- Strict CSP (
script-src 'self') blocks inline JS — but few WP sites deploy one
Escalate via admin session
fetch() to call wp-admin/admin-ajax.php or the REST API to create a new admin user, install a backdoored plugin, or exfiltrate the session cookie. Common weaponization: wpxf XSS-to-RCE modules, or hand-rolled fetch chains.- Victim is Administrator with
create_users/install_pluginscapability - No SameSite=strict on WP auth cookie (default is Lax)
- Nonce checks limit some AJAX actions but nonces are readable from the admin DOM
- Reputable admins rarely preview untrusted contributor drafts without inspection
The supporting signals.
| In-the-wild exploitation | None observed as of 2026-07-02. No campaigns tracked by Patchstack or Wordfence. |
|---|---|
| Public PoC | No public PoC repo yet. Wordfence Threat Intel entry describes the sink but withholds a working payload until patch uptake improves. |
| EPSS | Not yet scored (disclosed 2026-07-01). Expect low single-digit percentile — consistent with authenticated WP plugin XSS class. |
| KEV status | Not listed. CISA KEV does not include authenticated Contributor XSS bugs without active exploitation. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N — network-reachable, low complexity, low privileges, no user interaction, scope-changed to visitor browser, limited C/I impact. |
| Affected versions | JetWidgets For Elementor ≤ 1.0.21 |
| Fixed version | 1.0.22 (per Crocoblock changelog on WordPress.org) |
| Exposure population | JetWidgets For Elementor reports ~100,000+ active installs per WordPress.org. Only sites allowing Contributor+ accounts to reach the widget editor are actually reachable. |
| Disclosure | 2026-07-01, credited via Wordfence Bug Bounty / Patchstack coordinated disclosure to Crocoblock. |
| Reporter | Independent researcher via Wordfence / Patchstack (name embargoed pending advisory publication). |
noisgate verdict.
The single most decisive factor is the Contributor-level authentication requirement combined with limited blast radius — the payload runs in a visitor's browser, not on the server, and cannot pivot to fleet-scale compromise. This is a WordPress presentation plugin, not an identity, hypervisor, or edge component, so no role-multiplier floor applies.
Why this verdict
- Auth barrier holds: Contributor is not open-registration on the majority of production WordPress sites; the attacker must already have editorial access or a stolen credential.
- Blast radius is per-site, not fleet: stored XSS in a page-builder widget compromises one WordPress site's admin session at worst — no lateral movement, no supply-chain pivot, no cross-tenant impact.
- Role multiplier: N/A — JetWidgets is a presentation-layer Elementor add-on. It is not on the identity/hypervisor/backup/edge/CI catalog. There is no plausible deployment where the same bug ends in domain takeover or fleet compromise, so the role-floor rule does not raise the verdict.
- No KEV, no PoC, no campaigns — EPSS will land low; opportunistic mass exploitation is unlikely because the auth gate defeats spray-and-pray.
- Real-world friction: WAFs (Wordfence, Sucuri, Cloudflare) already block naive
<script>injection in POST bodies; reasonable admin hygiene (don't preview untrusted drafts in a session withinstall_plugins) further shrinks the window.
Why not higher?
It's not HIGH because a Contributor account is a real gate on most production sites, the impact is scoped to one site's admin session, and there is no path to server-side code execution without a second bug. HIGH would require either unauthenticated reachability or a role-multiplier deployment — neither applies to an Elementor widget pack.
Why not lower?
It's not LOW because stored XSS in a widely-installed plugin (~100k installs) that specifically targets editorial staff — the people with install_plugins — is a credible path to full site takeover on multi-author blogs, membership sites, and agency-hosted WordPress. The vendor's 6.4 MEDIUM captures that correctly.
What to do — in priority order.
- Update JetWidgets For Elementor to 1.0.22 or later — Vendor patch is the clean fix. For MEDIUM verdicts there is no noisgate mitigation SLA — schedule this into your standard WordPress plugin update window and complete within the noisgate remediation SLA of 365 days. If you run managed hosting with auto-updates enabled, verify it lands within the next cycle.
- Audit and restrict Contributor+ role assignment — Confirm that open registration does not grant Contributor, Author, or Editor by default. Set
default_roletosubscriberinwp_options. Review existing Contributor accounts for staleness. This shrinks the reachable population for every authenticated WP plugin bug, not just this one. - Deploy or tune a WordPress WAF virtual patch — Wordfence, Patchstack, and Sucuri will publish rule signatures for CVE-2026-11380 within days. Enable the rule feed and ensure it applies to
/wp-admin/admin-ajax.phpand REST endpoints. Buys coverage until the plugin update ships across your estate. - Enforce a Content-Security-Policy on the WP frontend and admin — A CSP with
script-src 'self' 'nonce-…'neutralizes inline stored XSS payloads even when the sink exists. Use a plugin like WP Content Security Policy or edge headers at Cloudflare. This is a structural defense against the entire class. - Instruct editors/admins not to preview untrusted contributor drafts in a privileged session — Use a separate browser profile or an incognito window without WP auth cookies to review submissions. Removes step 4 of the attack path entirely.
- MFA on wp-login.php — helpful for keeping the attacker out, but does nothing once a legitimate Contributor account is the attacker.
- Disabling XML-RPC — this bug is REST/admin-UI reachable; XML-RPC is not the sink.
- HTTPS / HSTS — transport encryption doesn't stop server-stored script from executing in a legitimately-loaded page.
- HttpOnly cookies alone — the payload runs in the admin's DOM and can call authenticated endpoints via
fetch()without ever reading the cookie.
Crowdsourced verification payload.
Run this on any Linux host with SSH access to your WordPress webroot(s), or wrap it in your config-management inventory to sweep the fleet. Invoke as ./check-cve-2026-11380.sh /var/www/html where the argument is the WordPress install root. No elevated privileges required beyond read access to wp-content/plugins/.
#!/usr/bin/env bash
# noisgate verification: CVE-2026-11380 — JetWidgets For Elementor stored XSS
# Usage: ./check-cve-2026-11380.sh /path/to/wordpress
set -u
WP_ROOT="${1:-/var/www/html}"
PLUGIN_DIR="$WP_ROOT/wp-content/plugins/jet-widgets-for-elementor"
FIXED_VERSION="1.0.22"
if [ ! -d "$WP_ROOT/wp-content/plugins" ]; then
echo "UNKNOWN: $WP_ROOT does not look like a WordPress install"
exit 2
fi
if [ ! -d "$PLUGIN_DIR" ]; then
# Try alternate slug (some Crocoblock releases used jet-widgets)
PLUGIN_DIR="$WP_ROOT/wp-content/plugins/jet-widgets"
fi
if [ ! -d "$PLUGIN_DIR" ]; then
echo "PATCHED: JetWidgets For Elementor not installed at $WP_ROOT"
exit 0
fi
# Extract version from the plugin header
HEADER_FILE=$(grep -rlE '^[[:space:]]*Plugin Name:.*Jet[[:space:]]*Widgets' "$PLUGIN_DIR" 2>/dev/null | head -n1)
if [ -z "$HEADER_FILE" ]; then
echo "UNKNOWN: could not locate plugin header in $PLUGIN_DIR"
exit 2
fi
INSTALLED=$(grep -iE '^[[:space:]]*\*?[[:space:]]*Version:' "$HEADER_FILE" | head -n1 | sed -E 's/.*Version:[[:space:]]*([0-9.]+).*/\1/')
if [ -z "$INSTALLED" ]; then
echo "UNKNOWN: could not parse plugin version"
exit 2
fi
# Semver compare: return 0 if $1 < $2
ver_lt() { [ "$1" = "$2" ] && return 1; [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; }
if ver_lt "$INSTALLED" "$FIXED_VERSION"; then
echo "VULNERABLE: JetWidgets For Elementor $INSTALLED at $PLUGIN_DIR (fixed in $FIXED_VERSION)"
exit 1
else
echo "PATCHED: JetWidgets For Elementor $INSTALLED at $PLUGIN_DIR (>= $FIXED_VERSION)"
exit 0
fi
If you remember one thing.
default_role is subscriber, and push the plugin update through your normal WordPress maintenance window over the next quarter. Do not let this jump the queue over any KEV or unauthenticated-RCE items on your board.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.