CSP Allowlists for External Tile Hosts in Tauri vs Web Builds: A Complete Guide

GeoLibre requires connect-src and img-src CSP entries in Tauri desktop builds, while web builds rely on CORS headers or the tile worker's allowlist instead.

GeoLibre loads raster tiles through MapLibre GL JS. Depending on your target platform, securing external tile sources follows fundamentally different paths. This guide breaks down exactly what allowlists you need to configure for Tauri desktop builds versus web browser builds, with precise file paths and working code examples from the opengeos/GeoLibre repository.

How Tauri Desktop Builds Handle External Tiles

In the desktop (Tauri) build, the application runs inside a native webview. The Content-Security-Policy (CSP) defined in tauri.conf.json serves as the sole gatekeeper for all external resources. Unlike browsers, the Tauri webview does not enforce CORS — the CSP entirely controls what tile servers MapLibre can reach.

Required CSP Directives

Two directives control tile fetching:

  • connect-src – governs XHR/fetch requests MapLibre uses to retrieve tile data
  • img-src – governs <img>-style requests used for raster tiles

The current Tauri CSP configuration lives in [apps/geolibre-desktop/src-tauri/tauri.conf.json](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src-tauri/tauri.conf.json):

connect-src 'self' ipc: http://ipc.localhost asset: data: blob: https:
               http://asset.localhost http://127.0.0.1:* http://localhost:*
               wss://collab.geolibre.app ws://127.0.0.1:* ws://localhost:*
img-src      'self' asset: data: blob: https: http://asset.localhost

Adding a New External Tile Host

Any tile server not covered by https: or the explicit http://asset.localhost entry must be added to both directives. For example, to enable OpenPlanetaryMap tiles:

connect-src … https://s3.us-east-2.amazonaws.com/opmmarstiles …
img-src      … https://s3.us-east-2.amazonaws.com/opmmarstiles …

Here is the complete configuration pattern:

// apps/geolibre-desktop/src-tauri/tauri.conf.json
{
  "app": {
    "security": {
      "csp": "default-src 'self'; connect-src 'self' https://my.tileserver.com …; img-src 'self' https://my.tileserver.com …"
    }
  }
}

How Web Builds Handle External Tiles

In the web (browser) build, GeoLibre is served as static files (via npm run build → apps/geolibre-desktop/dist/). The client bundle contains no hard-coded CSP. Instead, security is handled at the HTTP server layer through CORS headers or GeoLibre's tile worker proxy.

Option 1: CORS-Enabled Tile Servers

If the external tile server sends appropriate Access-Control-Allow-Origin headers, no client-side configuration is required. The browser permits the request automatically.

Option 2: Worker Proxy for CORS-Restricted Sources

If the tile server lacks CORS headers, GeoLibre routes requests through its tiles worker at [workers/tiles/src/allowlisted-fetch.ts](https://github.com/opengeos/GeoLibre/blob/main/workers/tiles/src/allowlisted-fetch.ts). This worker acts as a same-origin proxy.

Add your host to the worker's allowlist:

// workers/tiles/src/allowlisted-fetch.ts
export const ALLOWLISTED_PREFIXES = [
  "https://s3.us-east-2.amazonaws.com/opmmarstiles/",
  "https://my.tileserver.com/",   // ← new entry
];

The worker's entry point at workers/tiles/src/index.ts handles the actual CORS-free proxying logic.

Side-by-Side Comparison

Build Type Security Mechanism Configuration Location Key Requirement
Tauri desktop CSP headers in webview tauri.conf.json Explicit connect-src and img-src entries per host
Web browser CORS headers or worker proxy HTTP server or workers/tiles/src/allowlisted-fetch.ts Server CORS headers or worker allowlist entry

Practical Implementation: Adding a Custom Tile Source

Once your allowlists are configured, define the layer in your GeoLibre application. The pattern in apps/geolibre-desktop/src/lib/layers.ts demonstrates standard raster tile integration:

const layer = {
  id: "my-external-tiles",
  type: "raster",
  source: {
    type: "raster",
    tiles: ["https://my.tileserver.com/{z}/{x}/{y}.png"],
    tileSize: 256,
  },
};
store.addLayer(layer);

Key Files Reference

Summary

  • Tauri builds require explicit CSP allowlists in tauri.conf.json — no CORS enforcement exists in the webview
  • Web builds defer to CORS headers or the tile worker proxy — no client CSP is embedded
  • Add external hosts to both connect-src and img-src for Tauri compatibility
  • Use ALLOWLISTED_PREFIXES in the worker when CORS headers are unavailable
  • Always verify tile URLs use the correct protocol (https: vs http:) in your CSP entries

Frequently Asked Questions

Does GeoLibre support wildcard CSP entries for all HTTPS tile servers?

The https: scheme source allows any HTTPS origin in connect-src and img-src, which covers most commercial tile providers. However, specific HTTP hosts require explicit entries. Review your tauri.conf.json to confirm the wildcard is present and add individual hosts as needed for non-HTTPS sources.

Why does my tile layer work in browser but fail in Tauri desktop?

Browsers enforce CORS, which many tile servers support. Tauri's webview ignores CORS and relies entirely on CSP. Check that your tile host appears in both connect-src and img-src directives within tauri.conf.json, not just as a https: wildcard.

How do I debug CSP violations in Tauri?

Launch your Tauri app with developer tools enabled. CSP violations appear in the console with specific blocked URLs. Cross-reference these with your tauri.conf.json entries — the violation message indicates which directive blocked the request.

Can I use environment variables for dynamic CSP allowlists in Tauri?

Tauri's CSP is static JSON configuration. For dynamic hosts, you must rebuild with updated tauri.conf.json or implement a middleware proxy within your Rust backend that routes tile requests through a known-safe origin covered by your base CSP.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →