Skip to main content

Content Security Policy

If your site sends a Content-Security-Policy header, the browser blocks everything the policy does not allow, including Kaleidr's scripts, frames and requests. This page lists what to allow for each product. If your site sends no such header, you do not need this page.

How much you must allow depends on where the product runs:

ProductRunsWhat your policy must allow
ViewerIn an iframe that Kaleidr hostsThe loader script and the frame.
TileIn an iframe that Kaleidr hostsThe loader script, the session request and the frame.
ChatIn your pageThe loader script, requests to the API, injected styles, embedded fonts and images.
EditorIn your page, with its own mapAll of the above, plus the basemap host, map workers and map images.

For the two iframe products, the map and everything it loads are governed by Kaleidr's own policy inside the frame, not by yours. That is why their lists are short.

The hosts​

HostWhat it servesUsed by
https://cdn.kaleidr.comkaleidr.js and the product bundles it loads (chat.js, viewer.js, editor.js, tile.js).Every product, when you use the SDK.
https://api.kaleidr.comThe session exchange, and the requests the chat makes while it answers.Chat, Editor, Tile.
https://map-embed.kaleidr.comThe page that renders inside the Viewer and Tile iframe.Viewer, Tile.
https://tile.kaleidr.comThe basemap that the Editor's in-page map draws: style, tiles, sprites and fonts.Editor.

You do not need to allow Mapbox, MapTiler or OpenStreetMap hosts for any Kaleidr product. Earlier versions of this page listed them, and they can be removed. If your page runs its own map, that map's hosts are still yours to allow.

Viewer​

With the SDK element or Kaleidr.mount:

script-src https://cdn.kaleidr.com;
frame-src https://map-embed.kaleidr.com;

With the plain iframe snippet from Studio, there is no script:

frame-src https://map-embed.kaleidr.com;

A viewer needs no connect-src entry, because a viewer mounted without a key makes no request from your page.

Tile​

script-src https://cdn.kaleidr.com;
connect-src https://api.kaleidr.com;
frame-src https://map-embed.kaleidr.com;

connect-src is for the session exchange that the SDK performs with your publishable key before it creates the frame.

Chat​

script-src https://cdn.kaleidr.com;
connect-src https://api.kaleidr.com;
style-src 'unsafe-inline';
font-src data:;
img-src data: https:;
DirectiveWhy
script-src https://cdn.kaleidr.comThe loader and chat.js.
connect-src https://api.kaleidr.comThe session exchange and every question and answer.
style-src 'unsafe-inline'The chat adds one <style> element to your document's head. It carries no nonce.
font-src data:The chat's fonts are embedded in its bundle as data: URLs.
img-src data:The chat's icons are embedded as data: URLs.
img-src https:Place cards show photos. They load from image hosts that vary from place to place, so they cannot be listed here. With a narrower img-src, photos from hosts you have not allowed do not load.
img-src https: (site icons)Links in an answer, and a place's website on a place card, show the site's icon. It loads from Google's favicon service at https://www.google.com, which redirects to https://t0.gstatic.com through https://t3.gstatic.com. A narrower img-src needs https://www.google.com and https://*.gstatic.com, or the icons are missing and the links still work.

The chat bundle contains no map library and does not need 'wasm-unsafe-eval'. It draws on the map your page already has, so keep whatever your own map library requires: its script host, its tile and style hosts in connect-src and img-src, and worker-src blob: for Mapbox GL JS and MapLibre GL JS.

When the chat drives a Kaleidr viewer or tile element instead of your own map, add that product's lines as well, which means frame-src https://map-embed.kaleidr.com.

Editor​

script-src 'self' https://cdn.kaleidr.com;
style-src 'self' 'unsafe-inline';
connect-src 'self' https://api.kaleidr.com https://tile.kaleidr.com;
img-src 'self' data: blob: https://tile.kaleidr.com;
worker-src blob:;
font-src 'self' data:;
DirectiveWhy
script-src https://cdn.kaleidr.comThe loader and editor.js.
style-src 'unsafe-inline'The editor adds its stylesheets to the document from JavaScript, without a nonce.
connect-src https://api.kaleidr.comThe session exchange.
connect-src https://tile.kaleidr.comThe basemap's style, tiles, sprites and label fonts, which the editor's map fetches from your page.
img-src data: blob: https://tile.kaleidr.comMap imagery and icons. The map creates images from blob: and data: URLs.
worker-src blob:The map runs its workers from blob: URLs.
font-src data:The editor's interface fonts are embedded as data: URLs.

'wasm-unsafe-eval' is not part of the list. Add it to script-src only if the console reports that your policy blocked a WebAssembly compile from editor.js, which is the editor's 3D model decoder.

If you pass a full style URL as styleId, also allow that style's own hosts in connect-src and img-src.

Several products on one page​

Add up the lists. A page with a tile map and a chat panel that drives it needs:

script-src https://cdn.kaleidr.com;
connect-src https://api.kaleidr.com;
frame-src https://map-embed.kaleidr.com;
style-src 'unsafe-inline';
font-src data:;
img-src data: https:;

A complete policy​

The blocks above show what Kaleidr adds. A real policy also allows your own resources. This is a complete header for a site that serves everything else from its own origin and embeds a viewer and a tile map:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.kaleidr.com; connect-src 'self' https://api.kaleidr.com; frame-src https://map-embed.kaleidr.com; style-src 'self' 'unsafe-inline'

style-src 'unsafe-inline' is in this example for a reason that has nothing to do with Kaleidr's code: the snippets in these docs size the element with an inline style="display:block; height:480px" attribute, and a policy without 'unsafe-inline' ignores inline style attributes. If you want to keep inline styles blocked, size the element from your stylesheet:

kaleidr-map { display: block; height: 480px; }

The size the SDK gives its iframe is not affected. It is set from script, which a style policy does not block. The element's own display:block default is not affected either: it is not delivered as a <style> tag or a style attribute, so it needs no 'unsafe-inline'.

Nonces, hashes and strict-dynamic​

  • Scripts. The loader adds each product bundle as a <script src> element. A host-based script-src (as above) allows it. If your policy uses a nonce with 'strict-dynamic', put your nonce on the loader tag. The scripts it adds are then trusted through 'strict-dynamic' and the host entry is not needed.
  • Styles. The SDK cannot be given a nonce for the styles that Chat and Editor inject, and their content changes with releases, so a hash cannot be pinned either. Those two products need 'unsafe-inline' in style-src. Viewer and Tile inject no styles into your page.
  • Integrity. Do not add an integrity attribute to the loader tag. The file is updated in place. See CDN versioning.

What a blocked resource looks like​

Every block is reported in the browser console with the directive that caused it. Match it against this table.

SymptomConsole namesAdd
Nothing mounts. Kaleidr is not defined.script-srchttps://cdn.kaleidr.com to script-src.
The element stays empty. Console: [kaleidr:<product>] [kaleidr] failed to load …/embed/v1/<product>.jsscript-srcThe same. The loader was allowed (for example by a hash) but the bundle it loads was not.
Viewer or Tile shows an empty box.frame-src (or child-src, or default-src)https://map-embed.kaleidr.com to frame-src.
Tile, Chat or Editor does not start. The sessions request is blocked.connect-srchttps://api.kaleidr.com to connect-src.
The chat panel appears unstyled.style-src'unsafe-inline' to style-src.
The chat's icons or fonts are missing.img-src, font-srcdata: to both.
Place photos, or the icons beside links, are missing in the chat.img-srchttps: to img-src, or the hosts the console names.
The editor's panels appear but its map is blank.connect-src, worker-src or img-srchttps://tile.kaleidr.com to connect-src and img-src, blob: to worker-src and img-src.
The editor appears unstyled.style-src'unsafe-inline' to style-src.
The element ignores the height in its style attribute.style-srcNothing. Size it from a stylesheet.

Not every failure is a policy problem. If the sessions request is sent and comes back with status 401, 403 or 429, the policy allowed it and the API refused it. See Errors and CORS and allowed origins.

Roll out with report-only​

To add Kaleidr to a strict policy without breaking a production page:

  1. Send the candidate policy as Content-Security-Policy-Report-Only, alongside your current one, with a reporting endpoint you own.
  2. Exercise the embed: load the page, move the map, and for chat ask a few questions that return places with photos.
  3. Add the sources that appear in the reports to the directive each report names. Place photos are the usual source of new hosts.
  4. When the reports are quiet, move the policy to Content-Security-Policy.

What you do not need​

  • Mapbox, MapTiler or OpenStreetMap hosts, for any Kaleidr product.
  • 'unsafe-inline' in script-src. The loader adds product bundles as <script src> elements, never as inline scripts.
  • frame-ancestors. That directive controls who may frame your page, not what your page may frame.
  • Any entry for what happens inside the Viewer or Tile iframe.