A bouncer who stamps VIP wristbands on error messages because nobody told him errors aren't guests
User Profile Builder versions through 3.16.4 contain a type confusion in the wppb_log_in_user() function. When a registration request carries a username between 61 and 70 characters, WordPress core rejects it and returns a WP_Error object. The plugin calls absint() on that object before checking is_wp_error(), which coerces the error to integer 1 — the user ID of the default WordPress administrator. The plugin then generates an autologin nonce bound to user ID 1, handing the attacker a valid admin session. The attack is unauthenticated, requires a single HTTP POST, and needs zero user interaction. Affected versions: ≤ 3.16.4 (free and Pro editions). Fixed in: 3.16.5 (released July 16, 2026; 3.16.6 recommended for additional hardening).
The vendor's CRITICAL / 9.8 rating treats this as universally exploitable, but that overstates reality. The chain only fires when the per-form 'Automatically Log In after Registration' setting is enabled — a non-default, opt-in configuration found primarily on membership and community sites. WordPress installations that use UPB purely for profile editing or admin-approved registration (the more common use case) are not exploitable at all. The install base is modest at ~40,000 active sites globally. For the subset that *does* have auto-login enabled, however, the bug is devastating: one request, full admin, no friction. That warrants HIGH, not CRITICAL.
5 steps from start to impact.
Fingerprint the target
/wp-content/plugins/profile-builder/, the [wppb-register] shortcode output, or WPScan fingerprinting. This is trivially automatable at scale with WPScan, Nuclei content-detection templates, or httpx with custom matchers.- Target runs WordPress with User Profile Builder installed
- Only ~40,000 active installations globally — a very small target surface relative to the 800M+ WordPress ecosystem
/wp-content/plugins/profile-builder/ paths; WPScan or Nuclei user-agent signatures in access logsLocate a public registration form with auto-login enabled
[wppb-register] shortcode. On sites using UPB for membership or community features, this form is typically on a publicly accessible page. The attacker confirms registration is open and that the form triggers the autologin flow (observable from the response behavior or via trial registration).- A public-facing registration form using UPB shortcode exists
- 'Automatically Log In after Registration' is enabled on that form
- 'Automatically Log In after Registration' is a non-default, per-form setting — the majority of UPB installations do not enable it
- Some sites restrict registration behind email-domain allowlists, invite codes, or admin-approval workflows
Submit registration with oversized username
a characters) and any valid-looking email. This passes the plugin's frontend validation but exceeds WordPress core's 60-character user_login limit. wp_insert_user() returns a WP_Error object. No specialized tooling needed — a single curl -X POST suffices.- Registration form processes the request through
wppb_log_in_user()
- None — the request is structurally identical to a legitimate registration attempt
user_login field lengthType confusion yields admin autologin nonce
absint() on the WP_Error return value before performing the is_wp_error() check. PHP's absint() coerces the object to integer 1. The plugin treats this as a successful user creation with user ID 1 and generates an autologin nonce bound to that ID. Since user ID 1 is the WordPress administrator by default (~95%+ of installs), the attacker receives a valid authentication token via wp_set_auth_cookie().- User ID 1 exists and holds administrator privileges (default WordPress behavior)
- A small number of hardened installations reassign the admin to a higher user ID — but this is rare and not a documented WordPress hardening step
wp_set_auth_cookie calls for user ID 1 originating from the registration flow rather than wp-login.php; anomalous session creation events in security pluginsFull admin session established
wp_users and wp_options tables (including hashed credentials and PII), or pivot to the underlying server through the built-in theme/plugin file editor if DISALLOW_FILE_EDIT is not set.- Autologin nonce accepted by WordPress core
- Wordfence firewall virtual patch (deployed July 15, 2026) blocks exploitation for Wordfence Premium users; free-tier users received the rule 30 days later
wp-content/; wp-cron job anomaliesabsint()-before-is_wp_error() ordering in version 3.16.5, released July 16, 2026. Version 3.16.6 includes additional hardening and is the recommended target. This is the definitive remediation. Per the noisgate remediation SLA for HIGH, apply within 180 days. Test in staging first to confirm registration form behavior is preserved, then deploy to production.user_login POST parameter to ≤60 characters prevents the trigger condition. Wordfence shipped a virtual patch on July 15, 2026 — confirm it is active in your Wordfence configuration. Deploy within 30 days per the noisgate mitigation SLA.- WordPress MFA plugins (Wordfence 2FA, miniOrange, WP 2FA) — The autologin nonce bypasses the
wp-login.phpauthentication flow entirely. MFA hooks on the login form are never invoked because the plugin sets the auth cookie directly viawp_set_auth_cookie()in the registration handler. MFA provides zero protection against this specific attack path. - Rate limiting on the registration endpoint — The exploit requires exactly one HTTP POST request. Rate limiting will not block a single-request attack. It adds marginal friction to mass-scanning campaigns but does not prevent targeted exploitation.
- CAPTCHA on the registration form — While CAPTCHA impedes automated scanning, a human attacker solves it trivially. The attack is a single form submission with a long username and any email address. CAPTCHA reduces noise from bots but does not constitute a security control against this vulnerability.
The supporting signals.
| In-the-Wild Exploitation | No confirmed exploitation. Not listed in CISA KEV. No reports from Wordfence, Sucuri, or Patchstack of active campaigns targeting this CVE as of October 2026. No GreyNoise tags or Shadowserver scan data specific to this CVE. |
|---|---|
| Proof-of-Concept | Public PoC tooling exists. GitHub repo HORKimhab/CVE-2026-15826-CVE-2026-15748 contains a Python-based scanner with multi-threaded target scanning. Researcher Supakiad S. (m3ez) demonstrated the bug to Wordfence. No entry on pocindex.io, ExploitDB, or Metasploit. However, the attack requires only a single curl POST with a long username — weaponization is trivial even without published tooling. |
| EPSS | 0.03904 (3.9% probability of exploitation in the next 30 days). Moderate for a CVSS 9.8 — reflects the non-default configuration prerequisite dampening real-world exploitability. |
| KEV Status | Not listed in CISA KEV as of 2026-10-08. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — Network-accessible, low complexity, no privileges, no interaction. The vector does not encode the non-default configuration prerequisite, which inflates the base score beyond what real-world conditions warrant. |
| Affected Versions | User Profile Builder (slug: profile-builder) ≤ 3.16.4, both free and Pro editions. WordPress core is not affected — the bug is entirely in the plugin's wppb_log_in_user() function. |
| Fixed Versions | 3.16.5 (released July 16, 2026). Vendor recommends 3.16.6 for an additional hardening fix. No distro backports relevant — this is a WordPress plugin updated via the WordPress.org repository or manual upload. |
| Install Base & Exposure | ~40,000 active installations per wordpress.org plugin directory. All instances are internet-facing by nature. No specific Shodan/Censys/FOFA dorks published for this vulnerability. GreyNoise shows no tagged scanning activity. |
| Disclosure Timeline | Reported to Wordfence Bug Bounty: July 14, 2026. Validated: July 15. Patch released: July 16 (2-day vendor turnaround). Public NVD disclosure: August 15, 2026. Bounty paid: $975. |
| Researcher | Supakiad S. (GitHub: m3ez) via the Wordfence Bug Bounty Program. |
Sources.
Why this verdict
- Non-default prerequisite gates the entire chain. The 'Automatically Log In after Registration' setting is opt-in, per-form, and not enabled by default. The majority of the ~40,000 UPB installations use the plugin for profile editing or admin-approved registration — not frictionless autologin. This single prerequisite eliminates the majority of the installed base from exploitability, a factor the vendor's 9.8 score entirely ignores.
- No in-the-wild exploitation or KEV listing. Despite public disclosure on August 15 and a public PoC scanner on GitHub, there are no confirmed campaigns, no CISA KEV entry, and no GreyNoise scan activity nearly two months post-disclosure. EPSS at 0.039 corroborates low real-world exploitation momentum despite the high theoretical severity.
- Trivial exploitation when prerequisites are met keeps this at HIGH. The attack requires a single unauthenticated HTTP POST with a long username — no chaining, no brute force, no timing windows. When the autologin setting IS enabled and user ID 1 IS admin (the WordPress default), the chain is completely frictionless and yields full site takeover in seconds. This prevents a downgrade to MEDIUM.
- Role multiplier: WordPress sites are web-tier applications. The blast radius of a successful exploit is site-level: admin takeover, data exfiltration, webshell deployment, and potential lateral movement if the web server has internal network access. WordPress is not identity infrastructure, a hypervisor, CI/CD, a backup system, or a network edge appliance. In the minority of cases where WordPress hosts a customer portal with regulated PII or payment data (e.g., WooCommerce with stored payment methods), impact elevates to tenant-level, but User Profile Builder's 40K install base is predominantly blogs and small membership sites — not fleet-scale infrastructure. The high-value-role floor (CRITICAL) does not trigger. The standard-role floor (HIGH) is sustained by the zero-friction, zero-auth, single-request attack path for the exploitable subset.
Why not higher?
CRITICAL would require universal exploitability or a high-value-role floor trigger. The 'Automatically Log In after Registration' prerequisite is a genuine configuration gate — not a theoretical defense — that removes the majority of installations from the exploitable population. The component is a WordPress plugin with 40K installs occupying web-tier roles, not identity infrastructure or a network edge appliance. No confirmed in-the-wild exploitation exists to force an upward override.
Why not lower?
MEDIUM would undervalue the zero-friction attack path available to the exploitable subset. The bug requires no authentication, no user interaction, no chaining, and yields complete admin takeover in a single HTTP request. Public scanner tooling exists on GitHub and the attack is reproducible with curl alone. Any enterprise running UPB with autologin enabled is one POST away from full site compromise. The conditional nature narrows the population but does not reduce per-site impact.
Crowdsourced verification payload.
Run this script on the WordPress host (the server where WordPress files reside) as a user with read access to the WordPress installation directory. Invoke with: bash check_cve_2026_15826.sh /var/www/html (adjust the path to your WordPress root). Requires grep, sed, sort, and read access to the plugin directory. No database queries needed for the version check; optional wp-cli integration checks the autologin setting. Exit codes: 0 = VULNERABLE, 1 = PATCHED, 2 = UNKNOWN.
#!/usr/bin/env bash
# check_cve_2026_15826.sh — Detect CVE-2026-15826 in User Profile Builder
# Usage: bash check_cve_2026_15826.sh /path/to/wordpress
# Exit codes: 0=VULNERABLE, 1=PATCHED, 2=UNKNOWN
set -uo pipefail
WP_ROOT="${1:-/var/www/html}"
PLUGIN_FILE="$WP_ROOT/wp-content/plugins/profile-builder/index.php"
VULN_VERSION="3.16.4"
echo "=== CVE-2026-15826 Check ==="
echo "Target: $WP_ROOT"
echo ""
# Check plugin existence
if [ ! -f "$PLUGIN_FILE" ]; then
echo "UNKNOWN — User Profile Builder not found at $PLUGIN_FILE"
echo "The plugin may not be installed, or the path may be incorrect."
exit 2
fi
# Extract version from plugin header
VERSION=$(grep -i '^[[:space:]]*\*[[:space:]]*Version:' "$PLUGIN_FILE" 2>/dev/null | head -1 | sed 's/.*Version:[[:space:]]*//' | tr -d '[:space:]')
if [ -z "$VERSION" ]; then
echo "UNKNOWN — Could not parse version from $PLUGIN_FILE"
exit 2
fi
echo "Detected User Profile Builder version: $VERSION"
# Version comparison: is $VERSION <= $VULN_VERSION?
LOWER=$(printf '%s\n' "$VERSION" "$VULN_VERSION" | sort -V | head -n1)
if [ "$VERSION" = "$LOWER" ] && [ "$VERSION" != "$VULN_VERSION" ] || [ "$VERSION" = "$VULN_VERSION" ]; then
# Version is <= VULN_VERSION — but also check if equal is handled
if [ "$VERSION" = "$VULN_VERSION" ] || [ "$LOWER" = "$VERSION" ]; then
echo ""
echo "VULNERABLE — User Profile Builder $VERSION <= $VULN_VERSION"
echo "This version is affected by CVE-2026-15826."
echo ""
# Check autologin setting via wp-cli if available
if command -v wp &>/dev/null; then
echo "Checking 'Automatically Log In' setting via wp-cli..."
SETTINGS=$(wp option get wppb_general_settings --path="$WP_ROOT" --format=json 2>/dev/null || true)
if echo "$SETTINGS" | grep -qi 'automaticallyLogin\|auto_login\|autologin'; then
echo "WARNING: Auto-login setting appears ENABLED — exploitation is possible."
else
echo "INFO: Auto-login setting not detected via wp-cli."
echo "Manually verify: WP Admin > Profile Builder > Settings > check each form."
fi
else
echo "wp-cli not found. Manually verify if 'Automatically Log In after Registration'"
echo "is enabled on any registration form: WP Admin > Profile Builder > Settings."
fi
echo ""
echo "Remediation: Update to User Profile Builder >= 3.16.5"
echo "Immediate mitigation: Disable 'Automatically Log In after Registration' on all forms."
exit 0
fi
fi
# If we get here, version is > VULN_VERSION
echo ""
echo "PATCHED — User Profile Builder $VERSION is newer than $VULN_VERSION"
exit 1