Overview
A critical cross-site scripting (XSS) vulnerability has been disclosed in MapLibre GL JS, the widely used open-source interactive vector tile map library for web browsers. Tracked as CVE-2026-85061, the flaw lives in the library's own defensive sanitization routine — the exact code meant to strip dangerous markup before it reaches the DOM.
The bug is a textbook live-collection iteration hazard: DOM.sanitize() in src/util/dom.ts walks an element's attributes as a live NamedNodeMap while its companion removeAttributes() deletes entries from that same collection mid-iteration. Removing an item shifts every subsequent index down by one, and the loop's cursor doesn't account for the shift — so an attribute sitting immediately after a removed one gets silently skipped instead of sanitized.
Technical Details
| Field | Value |
|---|---|
| CVE ID | CVE-2026-85061 |
| Severity | Critical |
| CVSS Score | 10.0 |
| CWE | CWE-79 — Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') |
| Affected Component | DOM.sanitize(), src/util/dom.ts |
| Affected Versions | maplibre-gl-js ≤ 6.4.0 |
| Fixed Version | 6.4.1 |
| Authentication Required | None |
| User Interaction Required | Victim must render the malicious map content |
How It Works
MapLibre GL JS renders attribution strings — the small "credits" text shown for a map's tile/style source — by inserting them into the DOM and then running them through DOM.sanitize() to strip dangerous attributes like onload or ontoggle. That sanitizer iterates elem.attributes directly rather than snapshotting it into a static array first.
Because removeAttributes() mutates the very NamedNodeMap the loop is walking, deleting one dangerous attribute shifts the index of the next one, and the loop cursor advances past it without inspecting it. An attacker who controls an untrusted attribution string — via a custom map style, a third-party tile source, or any user-supplied attribution field — can craft two adjacent dangerous attributes so that the second one survives sanitization intact.
When MapLibre later inserts that "sanitized" markup via innerHTML, the surviving attribute (e.g. onload or ontoggle) executes as script the moment a victim's browser renders the map — no authentication, and no ability to brute-force the bypass required.
Impact Assessment
Who Is At Risk
Any application embedding MapLibre GL JS ≤ 6.4.0 is potentially exposed, particularly:
- Sites that render user-supplied or third-party map styles, including custom attribution strings
- Multi-tenant mapping platforms that let customers configure their own tile sources
- Applications embedding maps from less-trusted upstream data providers
Potential Attack Chain
- Malicious Style Injection — An attacker supplies a map style or attribution string containing two adjacent crafted attributes
- Sanitizer Bypass —
DOM.sanitize()'s live-collection bug skips the second attribute during attribute stripping - Script Execution — The surviving event-handler attribute (e.g.
onload,ontoggle) fires when the victim's browser renders the attribution control - Session/Data Compromise — Standard XSS outcomes follow: cookie/session theft, DOM manipulation, or pivoting into further attacks against the hosting application
Mitigation
Immediate Actions
- Upgrade to maplibre-gl-js 6.4.1 or later — this is the fix, and there is no configuration workaround for versions before it
- Audit for vendored or bundled copies of MapLibre GL JS in your dependency tree (direct and transitive) — a lockfile bump alone won't help if an older copy is vendored elsewhere
- Avoid rendering untrusted attribution strings or map styles as a defense-in-depth measure until the upgrade is deployed
Detection Opportunities
- Content Security Policy (CSP) violation reports for inline event handlers firing from map attribution controls
- Unexpected script execution correlated with map-rendering components in browser telemetry
Defence-in-Depth
- Enforce a strict CSP (no
unsafe-inline, nounsafe-eval) so that even a successful sanitizer bypass can't execute injected script - Treat any user- or partner-supplied map style/attribution data as untrusted input requiring server-side validation before it reaches the client
Background
Live-collection mutation-during-iteration bugs are a recurring class of DOM sanitization failure: NamedNodeMap, NodeList, and similar "live" browser collections update in place as the DOM changes, and any sanitizer that both reads and mutates the same live collection in one pass risks skipping entries exactly like this. The fix is straightforward — snapshot the collection into a static array before iterating — but the bug is easy to introduce and easy to miss in code review, since the sanitizer looks correct until an attacker deliberately orders dangerous attributes to exploit the index shift.
Given MapLibre GL JS's popularity as an open-source alternative to proprietary mapping SDKs, this vulnerability has broad reach across dashboards, logistics platforms, and any web application that embeds interactive maps.