Browsers and testing
Learn how to set up CSP directives and referrer policies and how to write automated tests.
CSP directives
As a mitigation for Cross-Site Scripting and other types of web security vulnerabilities, you may use a Content Security Policy (CSP) to specify security policies for your website. If you do, Mapbox GL JS requires the following CSP directives:
worker-src blob: ;
child-src blob: ;
img-src data: blob: ;
connect-src https://*.tiles.mapbox.com https://api.mapbox.com https://events.mapbox.com ;
Strict CSP environments
In strict CSP environments where worker-src blob: ; child-src blob: ;
cannot be used, you can use the mapbox-gl-csp.js
file instead of mapbox-gl.js
. The strict CSP bundle also requires manually setting the path to the GL JS worker source to use the mapbox-gl-csp-worker.js
file. Note that workers must obey the same-origin policy, which means that mapbox-gl-csp-worker.js
must be served from the same origin as the page that loads it.
<script src='https://api.mapbox.com/mapbox-gl-js/v3.9.0/mapbox-gl-csp.js'></script>
<script>mapboxgl.workerUrl = "https://api.mapbox.com/mapbox-gl-js/v3.9.0/mapbox-gl-csp-worker.js"; </script>
If you use the sandbox
directive, and your access token is restricted to certain URLs, the allow-same-origin
value is required. This allows requests to have a Referer
header that is not null
. See the section on Referrer Policies for further information.
Scoped CSP rules
In some rare scenarios, you may need even stricter CSP rules: If an attacker is able to inject arbitrary code in the same environment that Mapbox GL JS runs in, and you want to prevent data exfiltration through the Mapbox API, using an access token provided by the attacker.
In such situations, you can specify even tighter policy directives to restrict HTTP requests to read-only Mapbox API endpoints, or to endpoints that are owned by you and thus require a secret access token:
style-src
and script-src
Use https://api.mapbox.com/mapbox-gl-js/
for these directives. There are no endpoints under this prefix that allow writing, and Mapbox will not add such endpoints. Or, you can integrate Mapbox GL JS into your own JavaScript bundle.
connect-src
https://api.mapbox.com/v4/
. The Tiles API for vector, raster, static, or 3D model tiles only has read-only endpoints. Use this source directive as is. Mapbox will not add endpoints under this prefix that allow writing.https://api.mapbox.com/raster/v1/
. The endpoint for raster DEM tiles. It only has read-only endpoints. Use this source directive as is. Mapbox will not add endpoints under this prefix that allow writing. Or, you can restrict this to the actual tiles and TileJSON documents requested by your implementation.https://api.mapbox.com/rasterarrays/v1/
. The endpoint for rasterarray tiles. It only has read-only endpoints. Use this source directive as is. Mapbox will not add endpoints under this prefix that allow writing. Or, you can restrict this to the actual tiles and TileJSON documents requested by your implementation.https://api.mapbox.com/styles/v1/{username}/
. The Styles API has an endpoint to create new styles, or update existing ones. Restrict this endpoint to eithermapbox
, and/or usernames you control, so that the attacker cannot write to their account.https://api.mapbox.com/fonts/v1/{username}/
. The Fonts API has an endpoint for uploading new fonts. Restrict this endpoint to either Mapbox and/or usernames you control, so that the attacker cannot write to their account.https://api.mapbox.com/models/v1/{username}/
. The 3D Models API only has read-only endpoints. While we don’t provide any endpoints that allow model creation, restrict this endpoint to either Mapbox and/or usernames you control as a precautionary measure, so that the attacker cannot write to their account.https://api.mapbox.com/map-sessions/v1
. The endpoint for billed map sessions. While this endpoint allows writing data, an attacker cannot retrieve this data from Mapbox. Note the missing trailing slash.https://events.mapbox.com/
. The endpoint for anonymized user telemetry. While this endpoint allows writing data, an attacker cannot retrieve this data from Mapbox.
As a result, you can specify the following directives:
default-src 'none';
img-src data: blob:;
worker-src /mapbox-gl-csp-worker.js
style-src https://api.mapbox.com/mapbox-gl-js/ 'unsafe-inline';
script-src https://api.mapbox.com/mapbox-gl-js/ 'unsafe-inline';
connect-src
https://api.mapbox.com/v4/
https://api.mapbox.com/raster/v1/
https://api.mapbox.com/rasterarrays/v1/
https://api.mapbox.com/styles/v1/mapbox/
https://api.mapbox.com/fonts/v1/mapbox/
https://api.mapbox.com/models/v1/mapbox/
https://api.mapbox.com/map-sessions/v1
https://events.mapbox.com/
If you’re using custom styles and fonts, you’ll either have to change the /mapbox/
suffixes for styles
, fonts
and models
connect-src
directives to your account, or add a version of that URL with your account name as well as the Mapbox one.
For the proposed directives to be effective against data exfiltration, you must use an access token that has only read/list scopes, as per Mapbox recommended security practices.
Mapbox guarantees that these source directives required for loading map data are stable for the same Mapbox GL JS version. New Mapbox GL JS updates may introduce new endpoints, and if you use these directives you must check the Mapbox GL JS changelog for required updates to your CSP rules.
Referrer policies
If you use a URL-restricted access token, you have to make sure that the browser sends the correct referrer header. This is the default setting. But if you use the Referrer-Policy header on your website, pick a value that still sends a Referer
header, like no-referrer-when-downgrade
, origin
, origin-when-cross-origin
, or strict-origin
. Specifically, same-origin
and no-referrer
will never send a referrer header, and thus Mapbox API calls won't work.
If you limit the referrer to the origin, make sure that the URL you restrict your access token to doesn't contain path information, because the Origin
header doesn't contain a path by definition.
Automated tests
Run automated browser tests without an access token by setting the testMode
Map
option. The resulting Map
instance does not produce visual output, but still loads locally hosted fixtures for styles and tiles and maintains full JavaScript API compatibility.
This means that automated tests can exercise and assert state via the public API. This includes but is not limited to:
- Listen for interaction events like
click
,mouseover
etc on Layers. - Extract feature data with
map.queryRenderedFeatures()
. - Update view state
center
,pitch
,bearing
,map.easeTo()
,map.flyTo()
etc. - Interact with
Marker
andPopup
instances.
Example initialization of a Map
in testMode
:
const map = new mapboxgl.Map({
container: 'map',
zoom: 1,
fadeDuration: 0,
center: [0, 0],
testMode: true,
// Load inline style
style: {
version: 8,
sources: {
land: {
type: 'geojson',
data: `${location.origin}/test/browser/fixtures/land.json` // Load local geojson fixture
}
},
layers: [
{
id: 'land',
type: 'fill',
source: 'land',
paint: {
'fill-color': '#f0e9e1'
}
}
]
}
});