Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : May 4, 2026

CVE-2026-1865: User Registration & Membership <= 5.1.2 – Authenticated (Subscriber+) SQL Injection via membership_ids[] (user-registration)

CVE ID CVE-2026-1865
Severity Medium (CVSS 6.5)
CWE 89
Vulnerable Version 5.1.2
Patched Version 5.1.3
Disclosed April 6, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1865:

This vulnerability is an authenticated SQL Injection found in the User Registration & Membership plugin for WordPress, affecting versions up to and including 5.1.2. The flaw exists in the handling of the ‘membership_ids[]’ parameter during membership group operations. An attacker with Subscriber-level access or above can inject arbitrary SQL queries through this parameter, leading to data extraction from the WordPress database. The CVSS score of 6.5 indicates a medium-to-high severity issue.

Root Cause: The vulnerability originates from insufficient input sanitization and lack of prepared statements in the SQL query that processes the ‘membership_ids[]’ parameter. Although the full vulnerable code is not shown in the truncated diff, the CVE description and the nature of similar WordPress plugin vulnerabilities indicate that the subscription management or membership group update functionality directly injects user-supplied array values into SQL queries without parameterization. The diff shows changes in the AJAX handler class (AJAX.php) and membership-related functions, specifically around the ‘fetch_upgrade_path’ method (line 2750+), where a nonce check and capability check were added. This suggests the vulnerable endpoint was an AJAX action that accepted membership_ids[] as a parameter and used it in a SQL WHERE IN clause or similar construct without proper escaping or binding.

Exploitation: An authenticated attacker with Subscriber-level access can craft a malicious request to the WordPress admin-ajax.php endpoint, targeting the vulnerable AJAX action (likely ‘ur_membership_group’ or a related handler). The attacker sends a POST request with the ‘membership_ids[]’ parameter containing SQL injection payloads. For example, the attacker could set membership_ids[] to ‘0 UNION SELECT user_login, user_pass FROM wp_users– -‘ to extract user credentials. The lack of a nonce verification and capability check allowed lower-privileged users to reach the vulnerable code path. The attacker would need to be logged in as a Subscriber, but no additional privileges are required.

Patch Analysis: The patch introduces multiple security improvements. First, a nonce verification call ‘ur_membership_verify_nonce( ‘ur_membership_group’ )’ was added to the ‘fetch_upgrade_path’ method, ensuring the request originates from a legitimate source. Second, a capability check ‘current_user_can( ‘manage_options’ )’ was added, restricting the vulnerable functionality to administrators only. Third, the diff shows changes to the login flow for members (‘login_member’ now requires a password parameter) and the removal of automatic user deletion when payment method is missing. These changes collectively prevent unauthenticated or low-privilege exploitation by enforcing proper authorization and request validation before executing the SQL query.

Impact: Successful exploitation allows authenticated Subscribers and above to extract sensitive information from the WordPress database, including user credentials (username and password hashes), email addresses, session tokens, and any other data stored in the database. An attacker could leverage this to perform privilege escalation by retrieving administrator password hashes and attempting offline cracking, or by directly extracting API keys, configuration settings, or other sensitive plugin data. This can lead to full site compromise.

Differential between vulnerable and patched code

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

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;
-    }
-
-    /**
-     

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-1865
# Blocks SQL injection attempts targeting the membership_ids[] parameter via AJAX
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:20261865,phase:2,deny,status:403,chain,msg:'CVE-2026-1865 SQL Injection via membership_ids[]',severity:'CRITICAL',tag:'CVE-2026-1865'"
  SecRule ARGS_POST:action "@streq ur_membership_group" "chain"
    SecRule ARGS_POST:membership_ids "@rx (?:union|select|insert|update|delete|drop|alter|sleep|benchmark|load_file|intos+outfile|intos+dumpfile|information_schema|bORb|bANDb|--|#|/*)" "t:lowercase,t:urlDecode"

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