On July 14th, 2026, we received a submission for an Authentication Bypass vulnerability in User Profile Builder, a WordPress plugin with more than 40,000 active installations. This vulnerability makes it possible for unauthenticated attackers to log in as the user with ID 1, which is typically the site administrator, resulting in full administrative takeover of the site. The vulnerability is only exploitable on sites where the plugin’s Automatically Log In setting is enabled.
Props to Supakiad S. (m3ez) who discovered and responsibly reported this vulnerability through the Wordfence Bug Bounty Program. This researcher earned a bounty of $975.00 for this discovery. Our mission is to secure WordPress through defense in depth, which is why we are investing in quality vulnerability research and collaborating with researchers of this caliber through our Bug Bounty Program. We are committed to making the WordPress ecosystem more secure through the detection and prevention of vulnerabilities, which is a critical element to the multi-layered approach to security.
Wordfence Premium, Wordfence Care, and Wordfence Response users received a firewall rule to protect against any exploits targeting this vulnerability on July 15, 2026. Sites using the free version of Wordfence will receive the same protection 30 days later on August 14, 2026.
We provided full disclosure details to the Cozmoslabs team through our Wordfence Vulnerability Management Portal on July 15, 2026. The developer acknowledged the report on July 16, 2026, and released the fully patched version on the same day. We would like to commend the Cozmoslabs team for their prompt response and timely patch.
We urge users to update their sites to the latest patched version of User Profile Builder, version 3.16.5 at the time of this publication, as soon as possible.
Vulnerability Summary from Wordfence Intelligence
Technical Analysis
User Profile Builder is a popular WordPress plugin for creating custom frontend registration, login, and profile forms. It includes a documented “Automatically Log In after Registration” setting, which logs a user in immediately after they complete registration, without requiring email confirmation.
This vulnerability is the result of a type confusion flaw in how the plugin handles a failed user creation during the autologin flow.
The registration form renders a username field with a maximum length of 70 characters, and the plugin’s frontend validation only checks that the username is unique and passes WordPress core’s validate_username() function. A username between 61 and 70 characters passes these checks. However, WordPress core rejects any username longer than 60 characters, so when the oversized username is passed to wp_insert_user(), the function returns a WP_Error object.
function wppb_register_user( $global_request, $userdata ){
$wppb_module_settings = get_option( 'wppb_module_settings' );
$wppb_general_settings = get_option( 'wppb_general_settings' );
$user_id = null;
$new_user_signup = false;
if( isset( $wppb_general_settings['loginWith'] ) && ( $wppb_general_settings['loginWith'] == 'email' ) ){
$userdata['user_login'] = apply_filters( 'wppb_generated_random_username', WordPress_Creation_Kit_PB::wck_generate_slug( trim( $userdata['user_email'] ) ), $userdata['user_email'] );
}
/* filter so we can bypass Email Confirmation on register */
if ( isset( $wppb_general_settings['emailConfirmation'] ) )
$wppb_general_settings['emailConfirmation'] = apply_filters( 'wppb_email_confirmation_on_register', $wppb_general_settings['emailConfirmation'], $global_request );
if ( isset( $wppb_general_settings['emailConfirmation'] ) && ( $wppb_general_settings['emailConfirmation'] == 'yes' ) ){
$new_user_signup = true;
$userdata = $this->wppb_add_custom_field_values( $global_request, $userdata, $this->args['form_fields'] );
if( ! isset( $userdata['role'] ) ) {
$userdata['role'] = $this->args['role'];
}
$userdata['user_pass'] = wp_hash_password( $userdata['user_pass'] );
if( is_multisite() ){
/* since version 2.0.7 add this meta so we know on what blog the user registered */
$userdata['registered_for_blog_id'] = get_current_blog_id();
$userdata = wp_unslash( $userdata );
}
$userdata['form_name'] = $this->args['form_name'];
wppb_signup_user( $userdata['user_login'], $userdata['user_email'], $this->args['login_after_register'], $userdata );
}else{
if( ! isset( $userdata['role'] ) ) {
$userdata['role'] = $this->args['role'];
}
$userdata = wp_unslash( $userdata );
// change User Registered date and time according to timezone selected in WordPress settings
$wppb_get_date = wppb_get_register_date();
if( isset( $wppb_get_date ) ) {
$userdata['user_registered'] = $wppb_get_date;
}
// insert user to database
$user_id = wp_insert_user( $userdata );
}
return array( 'userdata' => $userdata, 'user_id' => $user_id, 'new_user_signup' => $new_user_signup );
}
The problem is that the plugin does not treat this WP_Error result as a failed registration. Instead, it continues through its success and autologin path. In the vulnerable version, the wppb_log_in_user() function calls absint() on the return value of wp_insert_user() before performing the is_wp_error() check:
function wppb_log_in_user( $redirect, $redirect_old, $user_id ) {
if( is_user_logged_in() ) {
return;
}
$wppb_general_settings = get_option( 'wppb_general_settings' );
$ec_bypass_forms = wppb_toolbox_get_settings( 'forms', 'ec-bypass' );
if ( is_array( $ec_bypass_forms ) && !empty( $_POST['form_name'] ) && in_array( sanitize_text_field( $_POST['form_name'] ), $ec_bypass_forms ) )
$should_bypass_ec = true;
else $should_bypass_ec = false;
if ( isset( $wppb_general_settings['emailConfirmation'] ) && ( $wppb_general_settings['emailConfirmation'] == 'yes' ) && !$should_bypass_ec ) {
return $redirect_old;
}
$user_id = absint( $user_id );
if ( ! $user_id || is_wp_error( $user_id ) ) {
return $redirect_old;
}
$user = get_userdata( $user_id );
if ( ! $user ) {
return $redirect_old;
}
if ( wppb_get_admin_approval_option_value() === 'yes' ) {
if( !empty( $wppb_general_settings['adminApprovalOnUserRole'] ) ) {
foreach ($user->roles as $role) {
if ( in_array( $role, $wppb_general_settings['adminApprovalOnUserRole'] ) ) {
return $redirect_old;
}
}
}
else {
return $redirect_old;
}
}
/* define redirect location */
if( $this->args['redirect_activated'] == 'No' ) {
if( isset( $_POST['_wp_http_referer'] ) ) {
$redirect = esc_url_raw($_POST['_wp_http_referer']);
} else {
$redirect = home_url();
}
}
if( empty( $redirect ) )
$redirect = wppb_curpageurl();
$redirect = apply_filters( 'wppb_login_after_reg_redirect_url', $redirect, $this );
$redirect = add_query_arg( wppb_get_autologin_query_args( $user_id ), $redirect );
Calling absint() on a WP_Error object coerces it to the integer 1. Because the resulting value is 1 rather than a WP_Error, the is_wp_error() check passes, get_userdata( 1 ) succeeds, and user ID 1 is typically the site’s original administrator account.
function wppb_get_autologin_query_args( $user_id ) {
$user_id = absint( $user_id );
$nonce = wp_create_nonce( 'autologin-' . $user_id . '-' . (int) ( time() / 60 ) );
wppb_store_autologin_user( $user_id, $nonce );
return array(
'autologin' => 'true',
'_wpnonce' => $nonce,
);
}
The plugin then generates a transient-backed autologin nonce bound to user ID 1 and returns a URL containing that nonce. When the attacker follows the returned URL, the plugin looks up the stored transient and calls wp_set_auth_cookie() with the bound user ID, authenticating the attacker as the administrator:
function wppb_autologin_after_registration(){
if( isset( $_GET['autologin'] ) && isset( $_REQUEST['_wpnonce'] ) ){
$nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) );
$uid = wppb_get_autologin_user_id( $nonce, false );
$arr_params = array( 'autologin', 'uid', '_wpnonce' );
$current_page_url = remove_query_arg( $arr_params, wppb_curpageurl() );
if ( ! $uid || ! get_userdata( $uid ) || ! wppb_verify_autologin_nonce( $nonce, $uid ) ) {
wp_redirect( $current_page_url );
exit;
}
wppb_get_autologin_user_id( $nonce, true );
wp_set_auth_cookie( $uid );
wp_redirect( $current_page_url );
exit;
}
}
As a result, an unauthenticated attacker can register with a 61-character username on a vulnerable site and be logged straight in as the site’s administrator if it exists with user ID 1.
As with all authentication bypass vulnerabilities that result in administrator access, this can lead to complete site compromise. Once authenticated as an administrator, the attacker can create additional administrator accounts, install malicious plugins or themes containing backdoors, modify site content, or exfiltrate sensitive data.
Important Note
We would like to draw attention once again to the fact that the vulnerability only critically affects websites where the user with ID 1 is the administrator.
Wordfence Firewall
The following graphic demonstrates the steps to exploitation an attacker might take and at which point the Wordfence firewall would block an attacker from successfully exploiting the vulnerability.
Disclosure Timeline
July 14, 2026 – We received the submission for the Authentication Bypass vulnerability in User Profile Builder via the Wordfence Bug Bounty Program.
July 15, 2026 – We validated the report and confirmed the proof-of-concept exploit.
July 15, 2026 – Full disclosure details were sent instantly to the vendor through our Wordfence Vulnerability Management Portal.
July 15, 2026 – Wordfence Premium, Care, and Response users received a firewall rule to provide added protection against any exploits that may target this vulnerability.
July 16, 2026 – The vendor acknowledged the report and released the fully patched version, 3.16.5.
August 14, 2026 – Wordfence Free users will receive the same protection.
Conclusion
In this blog post, we detailed an Authentication Bypass vulnerability within the User Profile Builder plugin affecting all versions up to, and including, 3.16.4. This vulnerability allows unauthenticated threat actors to log in as the site’s administrator and achieve complete site compromise by abusing a type confusion flaw in the plugin’s autologin flow. The vulnerability has been fully addressed in version 3.16.5 of the plugin.
We encourage WordPress users to verify that their sites are updated to the latest patched version of User Profile Builder as soon as possible considering the critical nature of this vulnerability.
Wordfence Premium, Wordfence Care, and Wordfence Response users received a firewall rule to protect against any exploits targeting this vulnerability on July 15, 2026. Sites using the free version of Wordfence will receive the same protection 30 days later on August 14, 2026.
If you know someone who uses this plugin on their site, we recommend sharing this advisory with them to ensure their site remains secure, as this vulnerability poses a significant risk.
The post 40,000 WordPress Sites affected by Authentication Bypass Vulnerability in User Profile Builder WordPress Plugin appeared first on Wordfence.
