Published : August 8, 2026

CVE-2026-66701: User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor <= 3.16.5 Missing Authorization PoC, Patch Analysis & Rule

Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 3.16.5
Patched Version 3.16.6
Disclosed July 28, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-66701:
This vulnerability affects the User Profile Builder plugin for WordPress, versions up to and including 3.16.5. The issue is a missing authorization check (CWE-862) that allows unauthenticated attackers to perform unauthorized actions. The severity is rated as CVSS 5.3 (Medium), but the exploit can lead to serious integrity and availability concerns.

Root Cause:
The root cause lies in the handling of attachment metadata during user profile registration and updates. In the file `profile-builder/features/email-confirmation/email-confirmation.php` (lines 299-305 and 330-336 in the vulnerable version), when a user submits a form containing an attachment field, the plugin extracts a numeric `meta-name` value from the submitted data. It then calls `update_user_meta($user_id, $value[‘meta-name’], trim($meta[$value[‘meta-name’]]))` and, crucially, `wp_update_post( array( ‘ID’ => trim( $meta[$value[‘meta-name’]] ), ‘post_author’ => $user_id ) )`. This `wp_update_post` call takes a post ID supplied directly from user input (`$meta[$value[‘meta-name’]]`) and changes its author to the registering user. The patch replaces this vulnerable block with a call to `wppb_save_attachment_id( trim( $meta[$value[‘meta-name’]] ), $value, $user_id )`, indicating that the original code lacked sufficient validation to ensure the provided ID corresponds to an attachment owned by the user or to verify the user’s authorization to perform such an action.

Exploitation:
An unauthenticated attacker can exploit this by submitting a registration or profile update form with a crafted attachment field where the `meta-name` is a numeric value representing the ID of a target post (e.g., a post, page, or other content type). By manipulating the submission, the attacker can cause the plugin to execute `wp_update_post` on that target post ID, changing its `post_author` to the attacker’s user ID. This effectively transfers ownership or modifies the authorship of arbitrary posts in the WordPress installation, without requiring any authentication or authorization. The attack vector is through the form processing endpoint that handles the `meta-name` fields, which is part of the standard registration or profile editing flow.

Patch Analysis:
The patch modifies `profile-builder/features/email-confirmation/email-confirmation.php` to replace the direct `update_user_meta` and `wp_update_post` calls with a single call to `wppb_save_attachment_id`. This new function presumably performs the necessary validation to ensure that the provided ID is a valid attachment and that the current user has the right to perform the action. By centralizing the logic into a dedicated function, the patch aims to enforce proper authorization checks before any post metadata modification occurs. The change effectively blocks unauthenticated attackers from manipulating post authorship.

Impact:
If exploited, an attacker can change the author of arbitrary posts, pages, or custom post types. This can lead to content defacement, unauthorized modification of site content, and potential privilege escalation scenarios if post authorship grants editorial or administrative capabilities elsewhere in the application. The integrity of the WordPress site’s content is compromised, and in some environments, the attacker may gain the ability to publish or alter content that appears under another user’s name, leading to reputational damage or further attacks.

Atomic Edge analysis of CVE-2026-66701:

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/profile-builder/admin/register-version.php
+++ b/profile-builder/admin/register-version.php
@@ -268,16 +268,16 @@
         // Plugin pages
         if( $notifications->is_plugin_page() ){

-            $notification_id = 'wppb_bf_2025';
+            $notification_id = 'wppb_bf_2026';

             $message = '<div class="wppb-bf-notice-container"><img style="max-width: 60px;width: 60px;" src="' . WPPB_PLUGIN_URL . 'assets/images/pb-logo.svg" />';

             if ( defined( 'WPPB_PAID_PLUGIN_DIR' ) && $license_status == 'expired' ){
                 $message .= '<div><p style="font-size: 110%;margin-top:0px;margin-bottom:4px;padding:0px;">' . '<strong>Renew your Profile Builder license this Black Friday! </strong>' . '</p>';
-                $message .= '<p style="font-size: 110%;margin-top:0px;margin-bottom: 0px;padding:0px;">Don't miss out on our <strong>best prices & only sale of the year</strong>. <br><a class="button-primary" style="margin-top:6px;margin-left: 0px !important;" href="https://www.cozmoslabs.com/account/?utm_source=pb-settings&utm_medium=clientsite&utm_campaign=BF-2025" target="_blank">Get Deal</a></p></div>';
+                $message .= '<p style="font-size: 110%;margin-top:0px;margin-bottom: 0px;padding:0px;">Don't miss out on our <strong>best prices & only sale of the year</strong>. <br><a class="button-primary" style="margin-top:6px;margin-left: 0px !important;" href="https://www.cozmoslabs.com/account/?utm_source=pb-settings&utm_medium=clientsite&utm_campaign=BF-2026" target="_blank">Get Deal</a></p></div>';
             } else {
                 $message .= '<div><p style="font-size: 110%;margin-top:0px;margin-bottom:4px;padding:0px;">' . '<strong>Get the best price for Profile Builder PRO this Black Friday!</strong>' . '</p>';
-                $message .= '<p style="font-size: 110%;margin-top:0px;margin-bottom: 0px;padding:0px;">This is a <strong>limited-time offer</strong>, so don't miss out on our <strong>only sale of the year</strong>. <br><a class="button-primary" style="margin-top:6px;margin-left: 0px !important;" href="https://www.cozmoslabs.com/black-friday/?utm_source=pb-settings&utm_medium=clientsite&utm_campaign=BF-2025" target="_blank">Get Deal</a></p></div>';
+                $message .= '<p style="font-size: 110%;margin-top:0px;margin-bottom: 0px;padding:0px;">This is a <strong>limited-time offer</strong>, so don't miss out on our <strong>only sale of the year</strong>. <br><a class="button-primary" style="margin-top:6px;margin-left: 0px !important;" href="https://www.cozmoslabs.com/black-friday/?utm_source=pb-settings&utm_medium=clientsite&utm_campaign=BF-2026" target="_blank">Get Deal</a></p></div>';
             }

             $message .= '</div><a href="' . wp_nonce_url( add_query_arg( array( 'wppb_dismiss_admin_notification' => $notification_id ) ), 'wppb_plugin_notice_dismiss' ) . '" type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss this notice.', 'profile-builder' ) . '</span></a>';
@@ -288,15 +288,15 @@

             if( wppb_bf_show_shared_promotion() ){

-                $notification_id = 'wppb_bf_2025_cross_promotion';
+                $notification_id = 'wppb_bf_2026_cross_promotion';

                 $message = '<img style="float: left; margin: 10px 8px 10px 0px; max-width: 20px;" src="' . WPPB_PLUGIN_URL . 'assets/images/pb-logo.svg" />';
                 $message .= '<img style="float: left; margin: 10px 8px 10px 0px; max-width: 20px;" src="' . WPPB_PLUGIN_URL . 'assets/images/pms-logo.svg" />';

                 if ( defined( 'WPPB_PAID_PLUGIN_DIR' ) && $license_status == 'expired' )
-                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder & Paid Member Subscriptions PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2025" target="_blank">Learn more</a></p>';
+                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder & Paid Member Subscriptions PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2026" target="_blank">Learn more</a></p>';
                 else
-                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder & Paid Member Subscriptions PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2025" target="_blank">Learn more</a></p>';
+                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder & Paid Member Subscriptions PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2026" target="_blank">Learn more</a></p>';

                 $message .= '<a href="' . wp_nonce_url( add_query_arg( array( 'wppb_dismiss_admin_notification' => $notification_id ) ), 'wppb_plugin_notice_dismiss' ) . '" type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss this notice.', 'profile-builder' ) . '</span></a>';

@@ -304,14 +304,14 @@

             } else {

-                $notification_id = 'wppb_bf_2025';
+                $notification_id = 'wppb_bf_2026';

                 $message = '<img style="float: left; margin: 10px 8px 10px 0px; max-width: 20px;" src="' . WPPB_PLUGIN_URL . 'assets/images/pb-logo.svg" />';

                 if ( defined( 'WPPB_PAID_PLUGIN_DIR' ) && $license_status == 'expired' )
-                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2025" target="_blank">Learn more</a></p>';
+                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2026" target="_blank">Learn more</a></p>';
                 else
-                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2025" target="_blank">Learn more</a></p>';
+                    $message .= '<p style="padding-right:30px;font-size: 110%;"><strong>Upgrade to Profile Builder PRO this Black Friday!</strong> Don't miss our only sale of the year. <a href="https://www.cozmoslabs.com/black-friday/?utm_source=wpdashboard&utm_medium=clientsite&utm_campaign=BF-2026" target="_blank">Learn more</a></p>';

                 $message .= '<a href="' . wp_nonce_url( add_query_arg( array( 'wppb_dismiss_admin_notification' => $notification_id ) ), 'wppb_plugin_notice_dismiss' ) . '" type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss this notice.', 'profile-builder' ) . '</span></a>';

@@ -382,8 +382,8 @@
 function wppb_bf_promotion_is_active(){

     $black_friday = array(
-        'start_date' => '11/24/2025 00:00',
-        'end_date'   => '12/02/2025 23:59',
+        'start_date' => '11/23/2026 00:00',
+        'end_date'   => '12/01/2026 09:59',
     );

     $current_date = time();
--- a/profile-builder/features/email-confirmation/email-confirmation.php
+++ b/profile-builder/features/email-confirmation/email-confirmation.php
@@ -299,13 +299,7 @@
 					if ( isset( $meta[$value['meta-name']] ) ){
                         if( !empty( $meta[$value['meta-name']] ) ) {
                             if (is_numeric($meta[$value['meta-name']])) {
-                                update_user_meta($user_id, $value['meta-name'], trim($meta[$value['meta-name']]));
-
-                                // use this to update the post author to the correct user
-                                wp_update_post( array(
-                                    'ID'            => trim( $meta[$value['meta-name']] ),
-                                    'post_author'   => $user_id
-                                ) );
+                                wppb_save_attachment_id( trim( $meta[$value['meta-name']] ), $value, $user_id );
                             } else {
                                 $wp_upload_array = wp_upload_dir(); // Array of key => value pairs

@@ -336,13 +330,7 @@
 					if ( isset( $meta[$value['meta-name']] ) ) {
                         if( !empty( $meta[$value['meta-name']] ) ) {
                             if (is_numeric($meta[$value['meta-name']])) {
-                                update_user_meta($user_id, $value['meta-name'], trim($meta[$value['meta-name']]));
-
-                                // use this to update the post author to the correct user
-                                wp_update_post( array(
-                                    'ID'            => trim( $meta[$value['meta-name']] ),
-                                    'post_author'   => $user_id
-                                ) );
+                                wppb_save_attachment_id( trim( $meta[$value['meta-name']] ), $value, $user_id );
                             } else {
                                 $wp_upload_array = wp_upload_dir(); // Array of key => value pairs

--- a/profile-builder/front-end/default-fields/avatar/avatar.php
+++ b/profile-builder/front-end/default-fields/avatar/avatar.php
@@ -164,7 +164,7 @@
             }
         } else {
             $attachment_id = $request_data[wppb_handle_meta_name( $field['meta-name'] )];
-            if ( isset( $attachment_id ) ) {
+            if ( isset( $attachment_id ) && wppb_verify_attachment_id( $attachment_id ) ) {
                 return absint( trim( $attachment_id ) );
             }
         }
--- a/profile-builder/front-end/default-fields/recaptcha/recaptcha.php
+++ b/profile-builder/front-end/default-fields/recaptcha/recaptcha.php
@@ -139,6 +139,18 @@
         $invisible_parameters = '';
     }

+    /* For Invisible reCAPTCHA the token is only produced once the async grecaptcha script has loaded and bound the
+    submit button. Until then the submit button behaves like a plain button, so an early click would submit the form
+    with an empty g-recaptcha-response. Since validation now fails closed on a missing token, disable the submit
+    button(s) until the widget is ready and re-enable them afterwards (same approach used for reCAPTCHA v3 login). */
+    $invisible_submit_selector   = 'jQuery( "input[type='submit'], button[type='submit']", jQuery( ".wppb-recaptcha-element" ).closest( "form" ) )';
+    $invisible_disable_submit_js = '';
+    $invisible_enable_submit_js  = '';
+    if ( $field['recaptcha-type'] === 'invisible' ) {
+        $invisible_disable_submit_js = $invisible_submit_selector . '.prop( "disabled", true ).addClass( "wppb-recaptcha-not-ready" );';
+        $invisible_enable_submit_js  = $invisible_submit_selector . '.prop( "disabled", false ).removeClass( "wppb-recaptcha-not-ready" );';
+    }
+
     if( $field['recaptcha-type'] === 'v3' ) {

         //the section below is properly escaped or the variables contain static strings
@@ -245,6 +257,10 @@
         <script>
             window.wppbRecaptchaCallbackExecuted = false;
             window.wppbRecaptcha = true;
+
+            /* keep the form from being submitted with an empty token before the invisible reCAPTCHA is ready */
+            ' . $invisible_disable_submit_js . '
+
             var wppbRecaptchaCallback = function() {
                 if( !window.wppbRecaptchaCallbackExecuted ){//see if we executed this before
                     ' . $callback_conditions . '.each(function(){
@@ -256,8 +272,8 @@
                             return;
                         }

-                        var recID = grecaptcha.render(
-                            $recaptchaElement.attr("id"),
+                        var recID = grecaptcha.render(
+                            $recaptchaElement.attr("id"),
                             {
                                 "sitekey" : "' . $pubkey . '",
                                 "error-callback": wppbRecaptchaInitializationError,
@@ -267,13 +283,20 @@

                         $recaptchaElement.data("wppb-recaptcha-id", recID);
                     });
+
+                    /* the invisible reCAPTCHA is now bound to the submit button, so it is safe to re-enable it */
+                    ' . $invisible_enable_submit_js . '
+
                     window.wppbRecaptchaCallbackExecuted = true;//we use this to make sure we only run the callback once
                 }
             };
-
+
             /* the callback function for when the captcha does not load propperly, maybe network problem or wrong keys  */
             function wppbRecaptchaInitializationError(){
                 window.wppbRecaptchaInitError = true;
+
+                /* the widget could not load, so re-enable the submit button and let the (fallback) submit below run */
+                ' . $invisible_enable_submit_js . '
             ';
     }

--- a/profile-builder/index.php
+++ b/profile-builder/index.php
@@ -3,7 +3,7 @@
  * Plugin Name: Profile Builder
  * Plugin URI: https://www.cozmoslabs.com/wordpress-profile-builder/
  * Description: Login, registration and edit profile shortcodes for the front-end. Also you can choose what fields should be displayed or add new (custom) ones both in the front-end and in the dashboard.
- * Version: 3.16.5
+ * Version: 3.16.6
  * Author: Cozmoslabs
  * Author URI: https://www.cozmoslabs.com/
  * Text Domain: profile-builder
@@ -11,8 +11,8 @@
  * License: GPL2
  * WC requires at least: 3.0.0
  * WC tested up to: 10.9
- * Elementor tested up to: 4.1.4
- * Elementor Pro tested up to: 4.1.4
+ * Elementor tested up to: 4.2.0
+ * Elementor Pro tested up to: 4.2.0
  *
  * == Copyright ==
  * Copyright 2014 Cozmoslabs (www.cozmoslabs.com)
@@ -447,7 +447,7 @@
  *
  *
  */
-define('PROFILE_BUILDER_VERSION', '3.16.5' );
+define('PROFILE_BUILDER_VERSION', '3.16.6' );
 define('WPPB_PLUGIN_DIR', plugin_dir_path(__FILE__));
 define('WPPB_PLUGIN_URL', plugin_dir_url(__FILE__));
 define('WPPB_PLUGIN_BASENAME', plugin_basename(__FILE__));

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.