You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
DOM.sanitize() in src/util/dom.ts iterated elem.attributes (a live NamedNodeMap) while calling elem.removeAttribute() in the same loop. Removing an attribute shifts subsequent attributes down by one index, causing the iterator to skip the adjacent attribute.
An attacker can provide an HTML payload with consecutive dangerous attributes (such as <details open onload="1" ontoggle="...">). The first attribute is stripped while the second survives and executes upon insertion into innerHTML via the attribution control without requiring user interaction (zero-click XSS).
Applications rendering untrusted/third-party style attribution strings or user-supplied custom attributions are impacted.
Patches
The issue has been resolved by creating a static snapshot of attributes using Array.from(elem.attributes) before iteration. Please upgrade to maplibre-gl version 6.4.1 (or latest).
Workarounds
Sanitizing the attribute field of a source before passing it down to maplibre
Fix DOM.sanitize leaving dangerous attributes behind when multiple consecutive attributes are present. Iterating the live NamedNodeMap from elem.attributes while calling removeAttribute skipped the attribute directly after a removed one, so a second dangerous attribute (for example an ontoggle on a <details open> element) could survive sanitisation and later execute (#8189) (by @0xKirisame)
Give custom layers the live globe transition in CustomRenderMethodInput.defaultProjectionData.projectionTransition, which was hardcoded to 1 for the whole globe/mercator transition, so a custom layer jumped straight to the fully bent globe while every other layer eased (#8169) (by @mondsichtung)
Avoid a per-query Array.sort() in cross-tile symbol matching (TileLayerIndex.findMatches), claiming the lowest-index unclaimed candidate in a single pass instead; reduces main-thread symbol-placement cost on dense/coincident symbol layers (#7797) (by @pholmstr)
Use texelFetch for exact DEM and color-relief elevation stop lookups instead of normalized texture coordinate arithmetic (#7640) (by @johncarmack1984)
Make default draggable markers keyboard-focusable and movable with the arrow keys (1 px per press, 10 px with Shift); custom marker elements stay application-owned (#8020) (by @smmariquit)
🐞 Bug fixes
Fix a permanent frame rate degradation after switching styles: every sprite reload marked its images as updated forever, making every in-view tile re-check and re-upload them on every frame. Also stop leaking the images of a replaced sprite, which were never removed from the image manager (#8052) (by @HarelM)
Prevent a rejected missing style image resolver from blocking successfully resolved images in the same batch (#8146) (by @birkskyum)
Explicitly request no browser color management when decoding raster-DEM tiles so their RGB-encoded elevation values are not changed (what would otherwise happen with gfx.color_management.mode = 1 in Firefox) (#8125) (by @tnikkel)
Let an abort reach an image or raster tile load that is still awaiting its transformRequest, so ImageSource.updateImage no longer loses the image it was just handed and an aborted tile is no longer fetched (#8071) (by @mondsichtung)
Fix raster tiles fading in again when they are reloaded, briefly flashing the map background, most visibly when switching projection (#8106) (by @mondsichtung)
Fix globe panning inverting and stalling near and across the poles by rotating the globe with a versor, keeping the drag direction consistent at every latitude. Panning also eases off as the cursor approaches the edge of the globe and continues past it, instead of stopping. The bearing is preserved while panning, as before (#5296) (by @jcolot)
Fix fill-extrusion-rounded-corner-distance producing spikes: corner arcs now land on the integer tile grid, and corners created by tile clipping are left sharp (#8153) (by @HarelM)
Fix a gesture which was held still before being released still flinging the map (#1303) (by @zdila)
Make fired/listened map events typed. This means that map.on("something", ...) (and once, listens) will now give you an typescript error and better autocomplete. If you relied on firing/listening custom events via the map, this still works via the escape hatches map.fire("something" as any) -> map.on("something" as any, ...) (#8072) (by @CommanderStorm)
Let a StyleImageInterface give a {renderWithWebGL} callback as its data, an escape hatch for plugin developers and advanced users that renders a style image on the GPU instead of moving its pixels through the CPU. Nothing new is possible that pixels could not already express, but an image that changes often, such as an animated icon, gets more performant (#7954) (by @lucaswoj)
Use integer vertex attributes for packed line data instead of float conversion (#7640) (by @johncarmack1984)
Use integer vertex attributes for packed circle, heatmap, symbol, and fill-extrusion data instead of float conversion (#7640, #8143) (by @johncarmack1984)
Redesign benchmarks to use vitest bench capabilities and remove custom build for benchmarks code (#982) (by @johncarmack1984)
🐞 Bug fixes
Fix terrain pan/zoom gestures losing the grabbed terrain point: gestures are now solved against the elevation of the terrain under the gesture instead of the frozen center elevation, so terrain under the pointer/fingers no longer slips during moving-centroid pinches and drags (#8067) (by @StrawberryJam22)
Fix ImageSource, VideoSource and CanvasSource leaking a GPU texture on every image update and on removal, and a resized texture losing its wrap and filter settings (#8094) (by @mondsichtung)
Fix map.queryRenderedFeatures() sometimes causing "Out of bounds" error due to race condition while loading tile data (#8064) (by @smvjohansenbouvet)
Fix zooming the globe with the scroll wheel or a two-finger pinch drifting away from the pointer while the globe is small on screen, instead of keeping the location under the pointer as it does when zoomed in (#8095) (by @mondsichtung)
Add the fill-extrusion-rounded-corner-distance layout property, which replaces each fill-extrusion corner with an arc spanning the given distance (in meters) along the adjacent edges. The distance is clamped to 20% of each adjacent edge's length so that short edges don't collapse, and near-straight corners (turns below 5°) are left untouched. Defaults to 0, which keeps corners sharp (#7934) (by @CommanderStorm)
Improve Mercator rendering performance by skipping a redundant clipping mask border pass (#8038) (by @DoFabien)
Add support for updating an ImageSource with an already-decoded image (HTMLImageElement, HTMLCanvasElement, ImageBitmap or ImageData) directly via ImageSource.updateImage({image}), skipping the network request (#7944) (by @mondsichtung)
Add GeoJSONSource.getClusterOptions to get a source's current cluster options (cluster, clusterMaxZoom, clusterRadius) (#7948) (by @lazerg)
Add MapOptions.rotateSpeed and MapOptions.pitchSpeed, the degrees the bearing/pitch change per pixel dragged (#7949) (by @clement-igonet)
Show a grab cursor over draggable markers, including on non-interactive maps (#8019) (by @hugosmoreira)
🐞 Bug fixes
Use role=img for non-interactive default markers and role=button when they become interactive (#7790) (by @cat0825)
Fix an error thrown when a paint property transitions between arrays of different length (#6606) (by @HarelM)
Fix renderer crash when RasterTileSource.setTiles/setUrl is called while the source contains errored tiles (#7911) (by @lazerg)
Fix 3D buildings disappearing when the camera pitches up to look near the horizon, by growing tile-culling bounds as the frustum's bottom edge (from pitch and FOV) approaches horizontal (#7633) (by @clement-igonet)
Fix globe latitude precision on some GPUs (e.g. Mali) by reformulating the mercator-to-sphere Y coordinate algebraically (exp + rational arithmetic instead of atan/sin/cos), avoiding float32 cancellation and imprecise hardware transcendentals near the equator; the runtime GPU atan-error measurement/correction this superseded has also been removed (#7419) (by @clement-igonet)
Fix a race in RasterTileSource.loadTile and ImageSource.load where a tile/image aborted during an awaited transformRequest passed an undefined AbortController into the image request queue, crashing it with TypeError: Cannot read properties of undefined (reading 'signal') (#8004) (by @jan-grzybek)
Fix setTerrain not destroying the previously active terrain when switching to a new configuration, which leaked its GPU resources and left the old source still configured as a terrain source (#7990) (by @lazerg)
Fix fill and line layers being rendered twice near the antimeridian on globe when looking at poles or when zoomed out (#6248) (by @pabueco)
The following incorporates all the pre-releases for version 6 changes.
Check-out our migration guide from v5 to v6 for more information.
✨ Features and improvements
⚠️ Switch to an ESM-only distribution (maplibre-gl.mjs). The UMD bundles (maplibre-gl.js, maplibre-gl-csp.js) are no longer published. The CSP-specific bundle is also dropped: the ESM build loads its worker as a real URL, so worker-src blob: is no longer required. Consumers using <script src=".../maplibre-gl.js"> must switch to <script type="module">, and consumers using import maplibregl from 'maplibre-gl' must switch to import * as maplibregl from 'maplibre-gl' or named imports. See the docs ESM section or our migration guide for migration steps. (#6254) (by @birkskyum)
⚠️ Interpolate the light position in spherical coordinates instead of cartesian ones, so that a transition keeps its radial distance. (#7919) (by @HarelM)
⚠️styleimagemissing is now a notify-only event instead of the previous callback that allowed to provide an image. This aligns the event with standard event semantics (notify, not resolve). Use Map.setMissingStyleImageResolver to on-demand supply images instead via an function that can now also be async. (#7892) (by @birkskyum)
⚠️Map now composes a Camera instead of extending it (Map extends Evented directly and forwards the camera API). The internal map.transform was removed — use map's public API instead or open a PR if you need something that's not exposed. Removed the internal transform.getMatrixForModel helper (#7800) (by @HarelM)
⚠️ All map events are now real classes that are instantiated when they are fired. Renamed the Maps' BoxZoom handler from MapLibreZoomEvent to MapBoxZoomEvent, added the rollstart/roll/rollend and style.load (as MapStyleLoadEvent) events to MapEventType, and added event classes and type-map for Marker, Popup, GeolocateControl and FullscreenControl. Removed MapDataEvent: the data/dataloading/dataabort events are now MapSourceDataEvent | MapStyleDataEvent, so source data events carry the full source info (sourceId, tile, sourceDataType, …). Added MapMovementEvent as the type for all camera-transition events (move/zoom/rotate/pitch/roll/drag and their start/end variants). Evented is now generic over an event-type map (Evented<EventType>) and is abstract, so subclasses get strongly-typed on/once/off automatically without re-declaring overloads — this also types the events on Camera/Style (via MapEventType) and on the sources (via the new SourceEventType) (#7789) (by @HarelM)
⚠️ Update maplibre-gl-style-spec to version 25, which now throws an error with warning severity instead of silently failing on encoutering legacy expressions (#7792) (by @HarelM)
⚠️ Removed the remaining mapbox references in the code and in the tests. This changes the #pragma mapbox to #pragma maplibre in case you have shader code that relied on it. (#7761) (by @HarelM)
⚠️zoomLevelsToOverscale default value was changed to 4 to support better handling of high level zoom with dense labels. This might have a side effect of changing a bit the results of queryRenderedFeatures and some rendering of polygon center label. To revert this change, set the value to undefined (#7537) (by @HarelM)
⚠️ Remove the second parameter from GeoJSONSource.setData (waitForCompletion) and remove the return value of this to allow future changes to the API (#7538) (by @HarelM)
⚠️ The TypeScript target has been updated to ES2022.
This results in smaller bundles and improved runtime performance by relying on modern JavaScript features and reducing transpilation. Consumers targeting browsers or using some tooling released before 2022 may need to transpile MapLibre or update. This change also aligns all internal build configurations to a single target instead of ES2016 + ES2019, avoiding inconsistencies in emitted code. (#7404) (by @CommanderStorm)
⚠️ WebGL (v1) support has been removed; WebGL2 is now required.
In practical terms, this will not change how you interact with the map.
This enables performance improvements (e.g. line opacity), Terrain3D enhancements, and several bug fixes.
WebGL2 support has been widely available for years, and usage of the legacy path had plateaued, so maintaining it no longer justified the added complexity.
To ease this breaking change, we have also refactored how we handle the case that no webgl is avaliable (e.g. due to browser restrictions).
You can now listen to the webgl error via .on("error").
See caniuse.com/webgl2 for ecosystem support and our RFC for details. (#7453) (by @CommanderStorm)
⚠️ Support geojson nested objects, this is a breaking change as it encodes __$json__ before properties that used to be an object. It also parses them back, but this is still a breaking change if you assumed this bug existed. (#6992) (by HarelM)
⚠️ Improve types for {get,set}LayoutProperty, {get,set}PaintProperty to be the actual type instead of string/any (#7481) (by @CommanderStorm)
⚠️ Refactored the Hash-based location control (the option that syncs map state to the URL like #map=5/1/2) to use URLSearchParams internally. This improves extensibility for custom use cases, but may break existing code that relies on the previous implementation. It also changes how certain edge cases are parsed—for example, strings like #​10%2F3.00%2F-1.00 are now accepted, and hashes like #foo are normalized to #foo=. (#7073) (by @CommanderStorm)
Validate the terrain passed to map.setTerrain, which was previously applied unchecked (#7941) (by @HarelM)
Improve runtime error warnings to point at the offending style location (e.g. layers[3].paint.line-color, layers[3].filter) instead of just logging the bare error message (#7869) (by @CommanderStorm)
Improve terrain render-to-texture preparation performance by skipping sources that are not rendered to terrain textures (#7863) (by @DoFabien)
Add Map.setMissingStyleImageResolver for resolving missing style images with sync or async callbacks (#7850) (by @birkskyum)
Add RasterTileSource#setPremultiplyAlpha(false) to preserve raw RGBA tile values when alpha is used for data instead of opacity (#7235) (by @plantain).
Drop the archived @mapbox/whoots-js dependency by inlining its single getTileBBox helper (#7838) (by @qorexdevs)
Debounce setImages broadcast to once per animation frame, fixing O(n²) serialization overhead when adding many images (#7614) (by @bradymadden97)
Improve terrain rendering performance by avoiding unnecessary terrain data lookups during Mercator render-to-texture passes (#7833) (by @DoFabien)
Reduce allocation pressure while constructing DEM data and sampling terrain elevations (#7814) (by @DoFabien)
Reuse terrain DEM texture when preparing terrain (#7813) (by @DoFabien)
Add fill-layer-opacity and line-layer-opacity paint properties, which apply opacity to the entire layer output uniformly (#7570) (by @CommanderStorm)
Build main and worker in same build context to extract shared chunk (#7745) (by @dangkyokhoang)
Revert the line-opacity-driven offscreen rendering introduced in #7490 (#7764) (by @CommanderStorm). The overlap-artefact fix is now driven by line-layer-opacity instead.
Improve ProjectionData matrix backing types for renderer and custom layer projection matrices (#6316) (by @cat0825)
Optimization: vertex shader opacity culling for lines and fills #7711 (by @xavierjs)
Use a shared FBO for the terrain cache render to texture #7637 (by @xavierjs)
Use flat to opt out of interpolation for constant shader varyings (#7661) (by @birkskyum)
Replace texImage2D with texStorage2D for immutable textures (#7643) (by @birkskyum)
Enable mipmaps for non-power-of-two raster tiles, reducing aliasing at high pitch (#7641) (by @birkskyum)
Use GLSL ES 3.00 layout qualifiers for vertex attribute locations, replacing runtime bindAttribLocation calls (#7644) (by @birkskyum)
Adopt isolatedDeclarations and switch dts emitter from tsgo to oxc (#7566) (by @birkskyum)
Add a new map creation option, terrainSkirtLength, which allows the removal of visually unappealing vertical artifacts when using a terrain along with a transparent background (#7523) (by @safwat-halaby)
Optimization for Feature State: Replace String-Indexed Object with Array (up to 3.4X speedup) (#7550) (by @xavierjs)
Expose getProjectionData function in custom layer args objects (#7471) (by @kubapelc)
Marked package sideEffects as CSS-only in package metadata, which may improve tree-shaking and reduce bundle size in some bundlers (#7258) (by @CommanderStorm)
🐞 Bug fixes
⚠️ Fix transparent, overlapping lines creating artefacts. This is fixed for line-opacity, but purposefully not for transparent line-color properties, thus still allowing transparent colors to stack their effect. (#7490) (by @CommanderStorm)
⚠️ Disable icon scaling with offset, this is a render breaking change which we have decided to incorporate in both maplibre-gl-js and maplibre-native (#7742) (by @springmeyer and @HarelM)
Log style validation warnings instead of treating them as errors, so that a filter mixing legacy and expression syntax no longer aborts the style load and blanks the map (#7941) (by @HarelM)
Validate raster-dem sources passed to map.addSource, which were previously skipped. Stop a source type the style spec has no schema for, such as one registered with addSourceType, from failing the whole style. Previously only canvas was let through (#7941) (by @HarelM)
Fix line-layer-opacity/fill-layer-opacity clipping away a subsequent layer that shares the same source (#7867) (by @CommanderStorm)
Fix stale terrain depth and coordinate framebuffers when terrain tiles change without camera movement (#7812) (by @DoFabien)
Fix a memory leak where aborting a worker request (e.g. a GeoJSON tile load cancelled while panning) left its promise pending forever, so the awaiting async frame and everything it captured was never released; Actor.sendAsync now rejects with an AbortError on abort (#7826) (by @kamil-sienkiewicz-asi)
Skip undefined properties during worker serialization (#7801) (by @xavierjs)
Fix conflicting reloads of tiles causing an error in queryRenderedFeatures (#7765) (by @ckolin)
Fix a race condition in geojson source after init and fast update data (#7734) (by @HarelM)
Fix camera jump on dragend with globe + terrain at low pitch (#7736) (by @kodeezabdullah)
Fix web font rendering by awaiting document.fonts.load() before TinySDF instantiation (#7735) (by @kodeezabdullah)
Remove the framebuffer completeness check that threw an unhandled Framebuffer is not complete error on transient GPU resource loss (e.g. when a tab wakes from sleep); incomplete framebuffers now self-heal on the next frame instead (#7303) (by @johanrd)
Avoid TypeErrors from style methods while the WebGL context is lost (#7710) (by @cyphercodes)
querySourceFeatures() throws 'Block overruns tile' on overzoomed MLT tiles because the reported encoding doesn't match the re-encoded MVT data (#7707) (by @ted-piotrowski)
Fix geometry length check for polygons and lines in LineBucket after duplicate vertex trimming(#7638) (by @widefire)
line-dasharray step transition lags one zoom level when the step's branches are data-driven (#7705) (by @lucaswoj)
Fix feature state bulk remove + feature set per-id set does not remove state of first feature (#7554) (by @xavierjs)
Remove error when actor doesn't have a registered message type for better usability of custom messages in workers (#7589) (by @HarelM)
Add touchZoomRotate.setZoomRate() and touchZoomRotate.setZoomThreshold() to customize touch zoom speed and pinch sensitivity (#7271) (by @itisyb)
Improve ability to communicate with imported scripts in workers and use makeRequest in workres as well (#7451) (by @HarelM)
Allow opacity and opacityWhenCovered in Marker and MarkerOptions to accept number in addition to string, and add maplibregl-marker-covered CSS class to Marker element when covered by 3D terrain or a globe (#7433) (by @YuChunTsao)
perf: add a bench for terrain rendering and fix _demMatrixCache lookup being wasted cycles by actually using the cache (#7400) (by @CommanderStorm)
🐞 Bug fixes
Fix polygon text label placement drifting far from center for convex polygons at high zoom due to coordinate rounding in geojson-vt (#7380) (by @CommanderStorm)
Ensure that a successful ArrayBuffer response from a custom protocol that is null/undefined is set to an empty ArrayBuffer (#7427) (by @neodescis)
Fix error in _contextRestored when map was initialized without a style (#7432) (by @mvanhorn)
Fix issue with the cache used for zoomLevelsToOverscale feature (#7450) (by @HarelM)
Update stylelint and fix old issues with the CSS (mainly change rgb to use spaces) (#7365) (by @HarelM)
Make line-cap, line-miter-limit, and line-round-limit data-driven properties, allowing per-feature values (#7351) (by @CommanderStorm)
GPU performance optimization: early culling of transparent symbols in vertex shaders (#7364) (by @xavierjs)
Add example showing how to measure map performance using built-in events (load, idle, render) (#7077) (by @CommanderStorm)
UX: Clarify error message language so if layout and paint properties are confused in setPaintProperty or setLayoutProperty (#6954) (by @Willjfield and @CommanderStorm)
🐞 Bug fixes
Fix startup crash caused by a stale async style load completing after the style was cleared or replaced (#7377)
Make fitBounds and fitScreenCoordinates respect the zoomSnap map option by snapping the zoom level down to keep bounds fully visible (#7332 (by @CommanderStorm)
Make jumpTo, easeTo, and flyTo respect the zoomSnap map option by snapping the zoom level to the nearest valid increment (#7333 (by @CommanderStorm)
Fix setState crash when switching styles while globe projection is active (#7314) (by @ashwinuae)
Prevent crashes when calling map.remove() immediately after creation by canceling in-flight style URL loads (#7368) (by @CommanderStorm)
Fixed symbol collision flickering by adding tolerance to GridIndex AABB comparison (#7360) (by @kkokkoejong)
Fix GeolocateControl leaking a movestart listener on the map after removal, which could also crash if the control was in active tracking state when removed (#7286) (by @johanrd)
Cap tile texture reuse pool to prevent unbounded VRAM growth during rapid zoom/pan (#7289) (by @johanrd)
Fix Marker click listener not removed on remove(), leaking the handler added in #7028 (#7287) (by @johanrd)
Fix Terrain GPU resource leak: free FBO, textures, and meshes when terrain is disabled via setTerrain(null) (#7288) (by @johanrd)
Fix guard against partial layout in PauseablePlacement (#7079) (by @garethbowker)
Change the return type of LngLatBounds.toArray() to use a more precise type (#7156) (by @n4n5)
Add anisotropicFilterPitch map option to set the pitch above which the anisotropic filter is applied to all raster layers, the default of which is 20° (#7134) (by @larsmaxfield)
npm warn Unknown env config "store". This will error in a future major version of npm. See `npm help npmrc` for supported config options.
npm warn Unknown project config "resolution-mode". This will stop working in the next major version of npm. See `npm help npmrc` for supported config options.
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: @watergis/maplibre-gl-terradraw@1.4.0
npm error Found: maplibre-gl@6.10.0
npm error node_modules/maplibre-gl
npm error dev maplibre-gl@"^6.0.0" from the root project
npm error
npm error Could not resolve dependency:
npm error peer maplibre-gl@"^4.0.0 || ^5.0.0" from @watergis/maplibre-gl-terradraw@1.4.0
npm error node_modules/@watergis/maplibre-gl-terradraw
npm error dev @watergis/maplibre-gl-terradraw@"^1.4.0" from the root project
npm error
npm error Conflicting peer dependency: maplibre-gl@5.24.0
npm error node_modules/maplibre-gl
npm error peer maplibre-gl@"^4.0.0 || ^5.0.0" from @watergis/maplibre-gl-terradraw@1.4.0
npm error node_modules/@watergis/maplibre-gl-terradraw
npm error dev @watergis/maplibre-gl-terradraw@"^1.4.0" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry this command with --force or --legacy-peer-deps to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error /runner/cache/others/npm/_logs/2026-09-16T00_59_26_813Z-eresolve-report.txt
npm error A complete log of this run can be found in: /runner/cache/others/npm/_logs/2026-09-16T00_59_26_813Z-debug-0.log
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
^5.6.1→^6.0.0^5.6.0→^6.0.0^5.5.0→^6.0.0MapLibre GL JS: XSS Sanitizer Bypass in DOM.sanitize() via Live NamedNodeMap Removal Skip
CVE-2026-85061 / GHSA-jrc7-96c5-q579
More information
Details
Impact
DOM.sanitize()insrc/util/dom.tsiteratedelem.attributes(a liveNamedNodeMap) while callingelem.removeAttribute()in the same loop. Removing an attribute shifts subsequent attributes down by one index, causing the iterator to skip the adjacent attribute.An attacker can provide an HTML payload with consecutive dangerous attributes (such as
<details open onload="1" ontoggle="...">). The first attribute is stripped while the second survives and executes upon insertion intoinnerHTMLvia the attribution control without requiring user interaction (zero-click XSS).Applications rendering untrusted/third-party style attribution strings or user-supplied custom attributions are impacted.
Patches
The issue has been resolved by creating a static snapshot of attributes using
Array.from(elem.attributes)before iteration. Please upgrade tomaplibre-glversion 6.4.1 (or latest).Workarounds
Sanitizing the attribute field of a source before passing it down to maplibre
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
maplibre/maplibre-gl-js (maplibre-gl)
v6.4.1Compare Source
🐞 Bug fixes
DOM.sanitizeleaving dangerous attributes behind when multiple consecutive attributes are present. Iterating the liveNamedNodeMapfromelem.attributeswhile callingremoveAttributeskipped the attribute directly after a removed one, so a second dangerous attribute (for example anontoggleon a<details open>element) could survive sanitisation and later execute (#8189) (by @0xKirisame)CustomRenderMethodInput.defaultProjectionData.projectionTransition, which was hardcoded to 1 for the whole globe/mercator transition, so a custom layer jumped straight to the fully bent globe while every other layer eased (#8169) (by @mondsichtung)v6.4.0Compare Source
✨ Features and improvements
Array.sort()in cross-tile symbol matching (TileLayerIndex.findMatches), claiming the lowest-index unclaimed candidate in a single pass instead; reduces main-thread symbol-placement cost on dense/coincident symbol layers (#7797) (by @pholmstr)texelFetchfor exact DEM and color-relief elevation stop lookups instead of normalized texture coordinate arithmetic (#7640) (by @johncarmack1984)🐞 Bug fixes
gfx.color_management.mode = 1in Firefox) (#8125) (by @tnikkel)transformRequest, soImageSource.updateImageno longer loses the image it was just handed and an aborted tile is no longer fetched (#8071) (by @mondsichtung)fill-extrusion-rounded-corner-distanceproducing spikes: corner arcs now land on the integer tile grid, and corners created by tile clipping are left sharp (#8153) (by @HarelM)v6.3.0Compare Source
✨ Features and improvements
map.on("something", ...)(andonce,listens) will now give you an typescript error and better autocomplete. If you relied on firing/listening custom events via the map, this still works via the escape hatchesmap.fire("something" as any)->map.on("something" as any, ...)(#8072) (by @CommanderStorm)StyleImageInterfacegive a{renderWithWebGL}callback as itsdata, an escape hatch for plugin developers and advanced users that renders a style image on the GPU instead of moving its pixels through the CPU. Nothing new is possible that pixels could not already express, but an image that changes often, such as an animated icon, gets more performant (#7954) (by @lucaswoj)🐞 Bug fixes
ImageSource,VideoSourceandCanvasSourceleaking a GPU texture on every image update and on removal, and a resized texture losing its wrap and filter settings (#8094) (by @mondsichtung)map.queryRenderedFeatures()sometimes causing "Out of bounds" error due to race condition while loading tile data (#8064) (by @smvjohansenbouvet)v6.2.0Compare Source
✨ Features and improvements
fill-extrusion-rounded-corner-distancelayout property, which replaces each fill-extrusion corner with an arc spanning the given distance (in meters) along the adjacent edges. The distance is clamped to 20% of each adjacent edge's length so that short edges don't collapse, and near-straight corners (turns below 5°) are left untouched. Defaults to0, which keeps corners sharp (#7934) (by @CommanderStorm)🐞 Bug fixes
v6.1.0Compare Source
✨ Features and improvements
ImageSourcewith an already-decoded image (HTMLImageElement,HTMLCanvasElement,ImageBitmaporImageData) directly viaImageSource.updateImage({image}), skipping the network request (#7944) (by @mondsichtung)GeoJSONSource.getClusterOptionsto get a source's current cluster options (cluster,clusterMaxZoom,clusterRadius) (#7948) (by @lazerg)global-stateexpressions insky.*,light.*andprojection.typeproperties (#7966, #7967, #7968) (by @CommanderStorm)MapOptions.rotateSpeedandMapOptions.pitchSpeed, the degrees the bearing/pitch change per pixel dragged (#7949) (by @clement-igonet)🐞 Bug fixes
role=imgfor non-interactive default markers androle=buttonwhen they become interactive (#7790) (by @cat0825)RasterTileSource.setTiles/setUrlis called while the source contains errored tiles (#7911) (by @lazerg)exp+ rational arithmetic instead ofatan/sin/cos), avoiding float32 cancellation and imprecise hardware transcendentals near the equator; the runtime GPUatan-error measurement/correction this superseded has also been removed (#7419) (by @clement-igonet)RasterTileSource.loadTileandImageSource.loadwhere a tile/image aborted during an awaitedtransformRequestpassed an undefinedAbortControllerinto the image request queue, crashing it withTypeError: Cannot read properties of undefined (reading 'signal')(#8004) (by @jan-grzybek)setTerrainnot destroying the previously active terrain when switching to a new configuration, which leaked its GPU resources and left the old source still configured as a terrain source (#7990) (by @lazerg)v6.0.0Compare Source
The following incorporates all the pre-releases for version 6 changes.
Check-out our migration guide from v5 to v6 for more information.
✨ Features and improvements
maplibre-gl.mjs). The UMD bundles (maplibre-gl.js,maplibre-gl-csp.js) are no longer published. The CSP-specific bundle is also dropped: the ESM build loads its worker as a real URL, soworker-src blob:is no longer required. Consumers using<script src=".../maplibre-gl.js">must switch to<script type="module">, and consumers usingimport maplibregl from 'maplibre-gl'must switch toimport * as maplibregl from 'maplibre-gl'or named imports. See the docs ESM section or our migration guide for migration steps. (#6254) (by @birkskyum)styleimagemissingis now a notify-only event instead of the previous callback that allowed to provide an image. This aligns the event with standard event semantics (notify, not resolve). UseMap.setMissingStyleImageResolverto on-demand supply images instead via an function that can now also be async. (#7892) (by @birkskyum)Mapnow composes aCamerainstead of extending it (MapextendsEventeddirectly and forwards the camera API). The internalmap.transformwas removed — use map's public API instead or open a PR if you need something that's not exposed. Removed the internaltransform.getMatrixForModelhelper (#7800) (by @HarelM)Maps'BoxZoomhandler fromMapLibreZoomEventtoMapBoxZoomEvent, added therollstart/roll/rollendandstyle.load(asMapStyleLoadEvent) events toMapEventType, and added event classes and type-map forMarker,Popup,GeolocateControlandFullscreenControl. RemovedMapDataEvent: thedata/dataloading/dataabortevents are nowMapSourceDataEvent | MapStyleDataEvent, so source data events carry the full source info (sourceId,tile,sourceDataType, …). AddedMapMovementEventas the type for all camera-transition events (move/zoom/rotate/pitch/roll/dragand theirstart/endvariants).Eventedis now generic over an event-type map (Evented<EventType>) and isabstract, so subclasses get strongly-typedon/once/offautomatically without re-declaring overloads — this also types the events onCamera/Style(viaMapEventType) and on the sources (via the newSourceEventType) (#7789) (by @HarelM)#pragma mapboxto#pragma maplibrein case you have shader code that relied on it. (#7761) (by @HarelM)zoomLevelsToOverscaledefault value was changed to 4 to support better handling of high level zoom with dense labels. This might have a side effect of changing a bit the results ofqueryRenderedFeaturesand some rendering of polygon center label. To revert this change, set the value toundefined(#7537) (by @HarelM)GeoJSONSource.setData(waitForCompletion) and remove the return value ofthisto allow future changes to the API (#7538) (by @HarelM)This results in smaller bundles and improved runtime performance by relying on modern JavaScript features and reducing transpilation. Consumers targeting browsers or using some tooling released before 2022 may need to transpile MapLibre or update. This change also aligns all internal build configurations to a single target instead of ES2016 + ES2019, avoiding inconsistencies in emitted code. (#7404) (by @CommanderStorm)
In practical terms, this will not change how you interact with the map.
This enables performance improvements (e.g. line opacity), Terrain3D enhancements, and several bug fixes.
WebGL2 support has been widely available for years, and usage of the legacy path had plateaued, so maintaining it no longer justified the added complexity.
To ease this breaking change, we have also refactored how we handle the case that no webgl is avaliable (e.g. due to browser restrictions).
You can now listen to the webgl error via
.on("error").See caniuse.com/webgl2 for ecosystem support and our RFC for details. (#7453) (by @CommanderStorm)
__$json__before properties that used to be an object. It also parses them back, but this is still a breaking change if you assumed this bug existed. (#6992) (by HarelM){get,set}LayoutProperty,{get,set}PaintPropertyto be the actual type instead ofstring/any(#7481) (by @CommanderStorm)Hash-based location control (the option that syncs map state to the URL like#map=5/1/2) to useURLSearchParamsinternally. This improves extensibility for custom use cases, but may break existing code that relies on the previous implementation. It also changes how certain edge cases are parsed—for example, strings like#​10%2F3.00%2F-1.00are now accepted, and hashes like#fooare normalized to#foo=. (#7073) (by @CommanderStorm)map.setTerrain, which was previously applied unchecked (#7941) (by @HarelM)layers[3].paint.line-color,layers[3].filter) instead of just logging the bare error message (#7869) (by @CommanderStorm)Map.setMissingStyleImageResolverfor resolving missing style images with sync or async callbacks (#7850) (by @birkskyum)RasterTileSource#setPremultiplyAlpha(false)to preserve raw RGBA tile values when alpha is used for data instead of opacity (#7235) (by @plantain).@mapbox/whoots-jsdependency by inlining its singlegetTileBBoxhelper (#7838) (by @qorexdevs)setImagesbroadcast to once per animation frame, fixing O(n²) serialization overhead when adding many images (#7614) (by @bradymadden97)fill-layer-opacityandline-layer-opacitypaint properties, which apply opacity to the entire layer output uniformly (#7570) (by @CommanderStorm)line-opacity-driven offscreen rendering introduced in #7490 (#7764) (by @CommanderStorm). The overlap-artefact fix is now driven byline-layer-opacityinstead.ProjectionDatamatrix backing types for renderer and custom layer projection matrices (#6316) (by @cat0825)flatto opt out of interpolation for constant shader varyings (#7661) (by @birkskyum)bindAttribLocationcalls (#7644) (by @birkskyum)terrainSkirtLength, which allows the removal of visually unappealing vertical artifacts when using a terrain along with a transparent background (#7523) (by @safwat-halaby)getProjectionDatafunction in custom layer args objects (#7471) (by @kubapelc)sideEffectsas CSS-only in package metadata, which may improve tree-shaking and reduce bundle size in some bundlers (#7258) (by @CommanderStorm)🐞 Bug fixes
line-opacity, but purposefully not for transparentline-colorproperties, thus still allowing transparent colors to stack their effect. (#7490) (by @CommanderStorm)raster-demsources passed tomap.addSource, which were previously skipped. Stop a source type the style spec has no schema for, such as one registered withaddSourceType, from failing the whole style. Previously onlycanvaswas let through (#7941) (by @HarelM)line-layer-opacity/fill-layer-opacityclipping away a subsequent layer that shares the same source (#7867) (by @CommanderStorm)Actor.sendAsyncnow rejects with anAbortErroron abort (#7826) (by @kamil-sienkiewicz-asi)undefinedproperties during worker serialization (#7801) (by @xavierjs)queryRenderedFeatures(#7765) (by @ckolin)Framebuffer is not completeerror on transient GPU resource loss (e.g. when a tab wakes from sleep); incomplete framebuffers now self-heal on the next frame instead (#7303) (by @johanrd)line-dasharraystep transition lags one zoom level when the step's branches are data-driven (#7705) (by @lucaswoj)v5.24.0Compare Source
✨ Features and improvements
load,idle,render) (#7077) (by @CommanderStorm)🐞 Bug fixes
Popupnot updating its position when switching between terrain/globe projections (#7468) (by @CommanderStorm)v5.23.0Compare Source
✨ Features and improvements
touchZoomRotate.setZoomRate()andtouchZoomRotate.setZoomThreshold()to customize touch zoom speed and pinch sensitivity (#7271) (by @itisyb)makeRequestin workres as well (#7451) (by @HarelM)opacityandopacityWhenCoveredinMarkerandMarkerOptionsto acceptnumberin addition tostring, and addmaplibregl-marker-coveredCSS class toMarkerelement when covered by 3D terrain or a globe (#7433) (by @YuChunTsao)_demMatrixCachelookup being wasted cycles by actually using the cache (#7400) (by @CommanderStorm)🐞 Bug fixes
_contextRestoredwhen map was initialized without a style (#7432) (by @mvanhorn)v5.22.0Compare Source
✨ Features and improvements
line-cap,line-miter-limit, andline-round-limitdata-driven properties, allowing per-feature values (#7351) (by @CommanderStorm)load,idle,render) (#7077) (by @CommanderStorm)setPaintPropertyorsetLayoutProperty(#6954) (by @Willjfield and @CommanderStorm)🐞 Bug fixes
fitBoundsandfitScreenCoordinatesrespect thezoomSnapmap option by snapping the zoom level down to keep bounds fully visible (#7332 (by @CommanderStorm)jumpTo,easeTo, andflyTorespect thezoomSnapmap option by snapping the zoom level to the nearest valid increment (#7333 (by @CommanderStorm)setStatecrash when switching styles while globe projection is active (#7314) (by @ashwinuae)map.remove()immediately after creation by canceling in-flight style URL loads (#7368) (by @CommanderStorm)fitBoundsignoringmaxZoomoption invertical-perspectiveprojection (#7372) (by @CommanderStorm)fill-pattern(#7326) (by @k-yle)v5.21.1Compare Source
🐞 Bug fixes
promoteIdparameter to geojson worker and refactor communication object (#7320) (by @HarelM)v5.21.0Compare Source
✨ Features and improvements
referrerPolicyoption toRequestParametersto allow controlling the referrer policy for tile requests (#7278) (by @Bingtagui404)Accept: image/webpheader for image requests (#7293) (by @johanrd)DOM.remove()andDOM.mouseButton()wrappers; use native APIs directly (baseline 2015) (#7295) (by @johanrd)setTransformRequestaccept an async function in addition to a sync function. (#7184) (by @kikuomax)
🐞 Bug fixes
jumpTo(#7267) (by @HarelM)playingevent listener and pause video on source removal (#7279) (by @johanrd)"reloading"state (#7284) (by @katemihalikova)GeolocateControlleaking amovestartlistener on the map after removal, which could also crash if the control was in active tracking state when removed (#7286) (by @johanrd)clicklistener not removed onremove(), leaking the handler added in #7028 (#7287) (by @johanrd)setTerrain(null)(#7288) (by @johanrd)PauseablePlacement(#7079) (by @garethbowker)v5.20.2Compare Source
🐞 Bug fixes
v5.20.1Compare Source
🐞 Bug fixes
raster-resampling: nearestwas not applied as expected (#7247) (by @yano-h)v5.20.0Compare Source
✨ Features and improvements
boxZoom.boxZoomEndoption to customize the action after Shift-drag box selection (#6397) (by @itisyb)resamplingpaint property for raster, hillshade, and color-relief layers (#7074) (by @larsmaxfield)🐞 Bug fixes
setUrl/setTiles(#7185) (by @madoci)v5.19.0Compare Source
✨ Features and improvements
LngLatBounds.toArray()to use a more precise type (#7156) (by @n4n5)anisotropicFilterPitchmap option to set the pitch above which the anisotropic filter is applied to all raster layers, the default of which is 20° (#7134) (by @larsmaxfield)Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
This PR was generated by Mend Renovate. View the repository job log.