CVE-2026-85061

MapLibre GL JS DOM.sanitize() XSS Sanitizer Bypass (CVE-2026-85061)

Initial Access Execution Last updated:

Detects exploitation and presence of CVE-2026-85061, a critical (CVSS 10.0) cross-site scripting (CWE-79) sanitizer bypass in the maplibre-gl npm package (<= 6.4.0). MapLibre's DOM.sanitize() iterates over an element's live NamedNodeMap while removing attributes; because removal mutates the live collection during iteration, indices shift and dangerous attributes such as onload/onerror/href=javascript: are skipped and survive sanitization. Untrusted map content (GeoJSON feature properties, popup HTML, marker/legend content) rendered through the sanitizer can therefore inject executable script into the DOM. This detection surfaces vulnerable maplibre-gl versions in build/deploy telemetry and runtime indicators of XSS payloads delivered via map popups (event-handler attributes, javascript: URIs, and CSP violation reports referencing maplibre bundles).

Vulnerability Intelligence

Public PoC

What is CVE-2026-85061 MapLibre GL JS DOM.sanitize() XSS Sanitizer Bypass (CVE-2026-85061)?

MapLibre GL JS DOM.sanitize() XSS Sanitizer Bypass (CVE-2026-85061) (CVE-2026-85061) maps to the Initial Access and Execution tactics — the adversary is trying to get into your network in MITRE ATT&CK.

This page provides production-ready detection logic for MapLibre GL JS DOM.sanitize() XSS Sanitizer Bypass (CVE-2026-85061), covering the data sources and telemetry it touches: Web Application Firewall logs, CSP violation reports, Proxy logs. The queries below are rated critical severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Initial Access Execution
Microsoft Sentinel / Defender
kusto
// Detect XSS payloads delivered via MapLibre popup/GeoJSON content and CSP violations referencing maplibre bundles
let suspiciousAttrs = dynamic(["onload=", "onerror=", "onmouseover=", "onfocus=", "onclick=", "javascript:", "<img", "<svg", "formaction="]);
union
(
    CommonSecurityLog
    | where DeviceVendor has "CEF" or RequestURL has "maplibre"
    | extend Payload = tostring(RequestContext)
    | where Payload has_any (suspiciousAttrs)
    | project TimeGenerated, SourceIP, DestinationIP, RequestURL, Payload, Signal="waf-xss-maplibre"
),
(
    // CSP violation reports (ingested as custom log) naming maplibre-gl bundles
    CSPViolation_CL
    | where blocked_uri_s has_any ("onload", "javascript", "inline") or source_file_s has "maplibre"
    | project TimeGenerated, SourceIP=client_ip_s, DestinationIP="", RequestURL=document_uri_s, Payload=blocked_uri_s, Signal="csp-violation-maplibre"
)
| order by TimeGenerated desc

Surfaces WAF/proxy requests carrying MapLibre popup XSS payloads (event-handler attributes and javascript: URIs) and CSP violation reports attributed to maplibre-gl bundles, indicating a sanitizer-bypass exploit attempt against CVE-2026-85061.

critical severity medium confidence

Data Sources

Web Application Firewall logs CSP violation reports Proxy logs

Required Tables

CommonSecurityLog CSPViolation_CL

False Positives

  • Security scanners (Burp, ZAP, Nuclei) probing the application with XSS test strings
  • Legitimate GeoJSON feature properties that contain the literal substring 'javascript:' or 'onload' in prose descriptions
  • Penetration testers validating the patch after upgrading to 6.4.1

Sigma rule & cross-platform mapping

The detection logic for MapLibre GL JS DOM.sanitize() XSS Sanitizer Bypass (CVE-2026-85061) (CVE-2026-85061) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: network_connection
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Detect vulnerable maplibre-gl version in lockfile

    Expected signal: File read of lockfile; process execution of grep referencing maplibre-gl.

  2. Test 2Simulate XSS payload delivery via GeoJSON property

    Expected signal: Outbound HTTP POST to a maplibre endpoint with a request body containing 'onerror=' and '<img'.

  3. Test 3Simulate javascript: URI sanitizer bypass in popup HTML

    Expected signal: HTTP GET to a maplibre render endpoint whose query contains 'javascript:' and multiple event-handler attributes.


Response Playbook

Triage

  1. Confirm the deployed maplibre-gl version by inspecting package-lock.json / yarn.lock and the served JS bundle; any version <= 6.4.0 is vulnerable and must be treated as exploitable.
  2. Determine whether the application renders untrusted content (GeoJSON feature properties, user-supplied popup/marker HTML, third-party legend content) through MapLibre popups — this is the required exploitation path.
  3. Review the matched request payloads for genuine XSS vectors (onload=, onerror=, javascript:, <svg onload>) versus benign strings, and correlate source IP/user against expected traffic and known scanners.
  4. Check browser CSP violation reports and any client-side error telemetry for inline-script executions attributed to maplibre bundles around the alert time.

Containment

  1. Upgrade maplibre-gl to >= 6.4.1 across all applications and redeploy; this is the authoritative fix (PR #8189 / commit 1da69f3).
  2. As an interim mitigation, enforce a strict Content-Security-Policy (no unsafe-inline, no inline event handlers) and server-side sanitize/escape all untrusted properties before they reach MapLibre popup/marker HTML.
  3. Block or rate-limit source IPs delivering confirmed XSS payloads at the WAF and disable rendering of user-controlled HTML in map popups until patched.

Evidence Collection

  1. Preserve full WAF/proxy request logs (URL, headers, body) for the matched events and export the served maplibre-gl bundle hash and version string.
  2. Capture CSP violation reports, browser console/error telemetry, and any session recordings showing script execution originating from map content.

Escalation Criteria

  • ! Escalate to incident response if payloads show session-token exfiltration, credential harvesting, or successful script execution (confirmed via CSP report or user report), not just probing.
  • ! Escalate if the vulnerable version is confirmed on an internet-facing production application that renders untrusted map content and cannot be patched within the SLA window.

Investigation Guide

Forensic Artifacts

  • > Served maplibre-gl bundle version string and file hash from CDN/web root
  • > package-lock.json / yarn.lock entries pinning maplibre-gl <= 6.4.0
  • > WAF/proxy request bodies containing XSS vectors and browser CSP violation report payloads

Tuning Guidance

Baseline the set of user agents and source IPs belonging to authorized DAST scanners and penetration testers and exclude them, or route their alerts to a separate low-priority queue. Constrain the URL/path filter to endpoints that actually embed maplibre-gl and render untrusted content to reduce prose-string false positives. Once all applications are confirmed on >= 6.4.1, downgrade severity to informational and retain the rule for regression detection.


Hunting Queries

Hunt for HTTP requests to maplibre-serving endpoints carrying XSS event-handler or javascript: vectors that indicate sanitizer-bypass attempts.

Hunting — KQL
kql
CommonSecurityLog | where RequestURL has "maplibre" | extend p=tostring(RequestContext) | where p matches regex @"(?i)on(load|error|mouseover)\s*=|javascript:|<svg" | project TimeGenerated, SourceIP, RequestURL, p
Hunting — SPL
spl
index=web sourcetype="waf:log" uri_path="*maplibre*" | regex _raw="(?i)on(load|error|mouseover)\s*=|javascript:|<svg" | table _time src_ip uri_path _raw

Atomic Red Team Tests

Test 1 Detect vulnerable maplibre-gl version in lockfile
linux

Greps the project lockfile for a maplibre-gl version <= 6.4.0 to confirm exposure.

Command

bash
grep -E 'maplibre-gl@?[^0-9]*([0-5]\.[0-9]+\.[0-9]+|6\.[0-4]\.0)' package-lock.json yarn.lock 2>/dev/null || echo 'no vulnerable pin found'

Cleanup

bash
true

Expected Telemetry

File read of lockfile; process execution of grep referencing maplibre-gl.

Expected Detection

Build/SCA scan flags maplibre-gl <= 6.4.0 as vulnerable to CVE-2026-85061.

Test 2 Simulate XSS payload delivery via GeoJSON property
linux

Sends an HTTP request carrying an onerror event-handler XSS vector to a maplibre popup rendering endpoint in a lab.

Command

bash
curl -s -X POST 'http://localhost:8080/map/popup' --data-urlencode 'props={"name":"<img src=x onerror=alert(document.domain)>"}' -H 'Content-Type: application/x-www-form-urlencoded'

Cleanup

bash
true

Expected Telemetry

Outbound HTTP POST to a maplibre endpoint with a request body containing 'onerror=' and '<img'.

Expected Detection

WAF/proxy detection rule matches the onerror event-handler XSS vector against a maplibre-serving path.

Test 3 Simulate javascript: URI sanitizer bypass in popup HTML
linux

Sends map popup HTML containing a javascript: href and a live-NamedNodeMap-skip-style multi-attribute element to emulate the DOM.sanitize() bypass.

Command

bash
curl -s 'http://localhost:8080/map/render?html=%3Ca%20id%3Dx%20href%3Djavascript%3Aalert(1)%20onclick%3Dalert(2)%3Eclick%3C%2Fa%3E'

Cleanup

bash
true

Expected Telemetry

HTTP GET to a maplibre render endpoint whose query contains 'javascript:' and multiple event-handler attributes.

Expected Detection

Detection rule matches javascript: URI and event-handler vectors in the maplibre request query.

Related Detections