A coat-check clerk who can rename any guest as the club owner on the front entrance list
The Import and export users and customers WordPress plugin before 2.5.2 lets an authenticated user with create_users but not promote_users submit a user import through the front-end that rewrites the role of an existing account. If the imported row sets role to administrator, the plugin updates that user's role without checking whether the importer can promote, so a Shop Manager (or any custom role with create_users) can escalate to full site admin.
Vendor severity HIGH/7.2 is measured accurately for the intended WooCommerce/membership deployment: create_users is a high-privilege capability but not by itself a path to admin, and the import endpoint is only reachable if an admin opted into front-end import. The result is a classic vertical privilege escalation with meaningful preconditions, so HIGH is appropriate—not CRITICAL because it is not unauth or low-priv, and not MEDIUM because successful exploitation grants full site takeover.
6 steps from start to impact.
Obtain an account with create_users but not promote_users
curl or a browser are sufficient to operate the plugin's front-end import feature.- A WordPress role exists with
create_usersbut lackingpromote_users - Attacker has valid credentials or a stolen session for that role
- Default WordPress roles do not grant
create_usersto non-administrators; custom/e-commerce roles are required - Account takeover of a Shop Manager typically requires credential theft, phishing, or insider action
create_users; WordPress audit logs can show account loginsLocate the front-end import page or AJAX endpoint
admin-ajax.php action intended for customer/user import. The attacker browses to the import form and confirms it accepts a CSV upload.- Site administrator enabled front-end import via shortcode or page
- The vulnerable plugin version is installed and active
- Many deployments keep imports confined to
wp-admin, limiting front-end reachable population - The import form may be hidden behind membership/login requirements beyond the already-authenticated session
Submit a CSV import with an administrator role assignment
administrator. The plugin processes the role update without invoking current_user_can('promote_users'), so the change is accepted.- Import function accepts a role field for existing users
- CSV format matches plugin expectations
- Target user exists
- The attacker must know a valid existing user identifier
- Some hardened deployments may disable role editing through import or validate columns, though the vulnerability means the check is missing
wp_usermeta / user roles may catch the changeWordPress updates the target user's role to administrator
administrator role. The attacker does not need the target user's password at this stage; the role change is immediate and persistent.- WordPress stores role in
usermetaoruser_level - No secondary authorization layer blocks the role transition
- If the target user has a different primary role cached, it may require re-login to reflect, but promotion is generally instant
administrator role assignmentsLog in as the promoted user and gain full admin control
- Attacker can authenticate as the promoted user (password reset, email access, or session takeover)
- WordPress admin panel accessible
- Two-factor authentication on the target user could block login, but many accounts lack 2FA
- Hardening that disables plugin/theme editor may slow post-exploit code execution, though admin can still exfiltrate data
Full site takeover and server code execution
- WordPress file editing / plugin installation is allowed
- Server permits PHP execution of modified files
- Hardened WordPress installations may disable file editor and plugin install, but admin can often re-enable via database if
unfiltered_htmlormanage_optionsis present - EDR/application allowlisting on the server may catch web shells, but many WordPress hosts lack this
promote_users in front-end import, eliminating the privilege escalation. Apply within 30 days (noisgate mitigation SLA for HIGH) and complete patching within 180 days (noisgate remediation SLA for HIGH).create_users and promote_users. This cuts off the vulnerable path immediately.create_users from all non-administrator roles — Review roles (WooCommerce Shop Manager, custom roles) and ensure only Administrators hold create_users. This removes the precondition for the exploit while retaining normal site operation for most stores.administrator by non-admin import using WP audit log plugins or SIEM. This does not stop the exploit but reduces time to detect and respond.- Two-factor authentication alone: an attacker with a valid session or cookie can call the import endpoint without re-authenticating.
- A WAF rule blocking CSV uploads: the import is a legitimate authenticated feature, so blocks may be bypassed or harm business flow.
- Disabling
admin-ajax.php: the import may be served on a front-end page, and disabling AJAX breaks much of WordPress functionality.
The supporting signals.
| In-the-wild status | No active exploitation reported; not in CISA KEV as of assessment. |
|---|---|
| Proof-of-concept availability | No public PoC or exploit module found in PocIndex/GitHub for CVE-2026-92541; exploitation requires a custom CSV import via standard HTTP requests. |
| EPSS score | 0.00462 (0.462% probability of exploitation in next 30 days); percentile not disclosed. |
| KEV status | Not listed in CISA Known Exploited Vulnerabilities Catalog. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H — high-privilege network attack, no user interaction, scope unchanged. |
| Affected versions | Plugin versions < 2.5.2. |
| Fixed version | 2.5.2 |
| Scanning/exposure data | No public internet-wide scan data (GreyNoise/Shodan/Censys) for this WordPress plugin; exposure is self-hosted and opt-in. |
| Disclosure date | 2026-09-20 |
| Reporting researcher/org | Not disclosed in official CVE record. |
Sources.
- CVE.org record CVE-2026-92541
- NVD detail CVE-2026-92541
- WordPress plugin page — Import Export WordPress Users and WooCommerce Customers
- Wordfence Threat Intelligence database
- Patchstack WordPress vulnerability database
- FIRST EPSS model
- CISA Known Exploited Vulnerabilities Catalog
- GitHub Advisory Database query for CVE-2026-92541
Why this verdict
- Friction audit: The attacker must already hold a
create_userscapability, which is a high-privilege capability typically assigned to Shop Manager or custom roles on WooCommerce/membership sites; default WordPress roles do not grant it to non-admins. This narrows the exposed population to sites that deliberately create lower-privileged user-import roles. - Front-end exposure: The vulnerable import must be enabled on a public page or AJAX endpoint; many administrators keep imports confined to
wp-admin, adding a deployment-specific prerequisite. - Role multiplier: On WooCommerce/membership sites where Shop Manager is a standard role and this plugin is installed, successful promotion to administrator yields plugin/theme editing, code execution, and mass customer data egress; that high-value outcome plausibly represents ≥1% of the plugin's install base, flooring the verdict at HIGH.
- Baseline: The vendor CVSS 7.2 (
PR:H) already accounts for the elevated starting privileges; after friction and role analysis, a mild downgrade to 7.0 reflects the default-role non-exposure while preserving the HIGH floor.
Why not higher?
Not CRITICAL because the attacker must already possess a high-privilege capability and the vulnerable front-end import is opt-in; default WordPress installs without custom user-import roles are unaffected. There is no evidence of in-the-wild exploitation, KEV listing, or public PoC. The pre-auth network blast radius is zero, so the 9.0+ critical class does not apply.
Why not lower?
Friction cannot pull the verdict below HIGH because on the plugin's core use case (WooCommerce/membership stores with Shop Manager) a successful chain gives full administrative control and potential mass data egress. The promote_users gap is exactly the kind of vertical privilege escalation that turns a semi-trusted user into a site owner; residual risk after patching/detection is not enough to justify MEDIUM on the role-multiplier floor.
Crowdsourced verification payload.
Run on the WordPress application host that serves the plugin files. Example: bash check_cve-2026-92541.sh /var/www/html (requires read access to wp-content/plugins). If run from within the WordPress root, omit the argument.
#!/usr/bin/env bash
# CVE-2026-92541 check for WordPress Import and export users and customers < 2.5.2
set -euo pipefail
WP_ROOT="${1:-$(pwd)}"
VULN_PLUGIN_SLUGS=(
'users-customers-import-export-for-wp-woocommerce'
'import-export-users-and-customers'
'import-export-users-customers'
)
FIXED_VERSION='2.5.2'
plugin_dir=''
for slug in "${VULN_PLUGIN_SLUGS[@]}"; do
if [ -d "${WP_ROOT}/wp-content/plugins/${slug}" ]; then
plugin_dir="${WP_ROOT}/wp-content/plugins/${slug}"
break
fi
done
if [ -z "$plugin_dir" ]; then
echo "UNKNOWN: plugin directory not found under ${WP_ROOT}/wp-content/plugins"
exit 0
fi
version_file="${plugin_dir}/$(basename "$plugin_dir").php"
[ -f "$version_file" ] || version_file=$(find "$plugin_dir" -maxdepth 1 -name '*.php' | head -n1)
version=$(grep -m1 '^ \* Version:' "$version_file" 2>/dev/null | awk '{print $NF}' || true)
[ -n "$version" ] || version=$(grep -m1 '^Version:' "$version_file" 2>/dev/null | awk '{print $2}' || true)
if [ -z "$version" ]; then
echo "UNKNOWN: could not parse plugin version from $version_file"
exit 0
fi
if [ "$(printf '%s\n%s\n' "$version" "$FIXED_VERSION" | sort -V | head -n1)" = "$version" ] && [ "$version" != "$FIXED_VERSION" ]; then
echo "VULNERABLE: found plugin version ${version}, fixed version ${FIXED_VERSION}"
exit 2
else
echo "PATCHED: found plugin version ${version}"
exit 0
fi