Image hosts
For <img> loads — raster map tiles, remote pictures, and logos. The request is one-way and
GET-only, so it’s low risk. This is exactly what a map drawn from OpenStreetMap tiles needs.
A mini app runs walled-in, and by default its sandbox can’t reach
the internet at all — the browser blocks every external image, fetch, and request (the app’s content
policy starts at default-src 'none'). That’s deliberate: an app you fork or run from the store
can’t phone home or quietly ship your data somewhere.
But some apps genuinely need one outside resource — most often map tiles or a remote image. For those, you grant the app a short, explicit list of hosts, and Catalyst compiles exactly those hosts into the app’s sandbox rules. Nothing else gets through.
There are two separate lists, because loading an image and making a data request carry very different risk:
Image hosts
For <img> loads — raster map tiles, remote pictures, and logos. The request is one-way and
GET-only, so it’s low risk. This is exactly what a map drawn from OpenStreetMap tiles needs.
Connect hosts
For fetch / XHR — vector map tiles and JSON / REST APIs. This is a full two-way
channel, so it’s reviewed more strictly. It’s also finicky: these requests are CORS-checked and
the sandbox’s origin is null, so many hosts reject them — a JSON API or a vector-tile map
often won’t work unless that host explicitly allows Origin: null.
Each list is a set of bare hostnames — tile.openstreetmap.org, or a single leading wildcard
like *.tile.openstreetmap.org. https is always forced, so you don’t write a scheme; ports,
paths, and a bare * are rejected. You can grant up to 10 hosts per list.
The canonical case is a slippy map drawn from OpenStreetMap’s raster tiles. It needs one image host and no connect host at all:
Ask the assistant to build the map. For example: “Build me a map centered on New York using Leaflet.” Leaflet isn’t one of the built-in libraries, so the assistant adds it as an on-demand package and writes the component.
Grant the tile host as an image host. The assistant usually does this for you — it wrote the
tile URL, so it knows the host. If a tile load is blocked, add *.tile.openstreetmap.org under
Image hosts (see How to grant a host below).
The tiles render. Leaflet builds each tile URL like
https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png, and with the host granted the browser now
allows those image loads.
import React, { useEffect, useRef } from 'react';import L from 'leaflet'; // added on demand — ask the assistant for it
export default function MapApp() { const ref = useRef(null); useEffect(() => { const map = L.map(ref.current).setView([40.71, -74.0], 12); // Tile loads are <img> requests — covered by the image host grant. L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap', }).addTo(map); return () => map.remove(); }, []); return <div ref={ref} className="h-screen w-full" />;}You don’t have to use Leaflet — a hand-rolled map that places tiles as plain <img> elements works
the same way, since both just load images from the granted host.
There are three ways a host ends up on an app’s list — you’ll mostly rely on the first:
*.tile.openstreetmap.org. Click it and the host is added, the app reloads with the new rules,
and the resource appears.A grant-less app reaching a tile server is about as risky as opening a maps website — it has none of your Catalyst data to leak. So an image-only grant on an app with no data grants is the low-friction path.
The combination to watch is an app that pairs a network host with a data grant (a collection or a workflow). That’s the shape that could send your data somewhere, so it’s the case Catalyst reviews closely before an app is published to the store. Keep grants minimal: only the hosts an app actually needs, and don’t pair network reach with data access unless the app genuinely requires both.
The example above uses OpenStreetMap’s public tile server, which is run by volunteers for light,
community use under its
Tile Usage Policy. That policy requires
requests to identify themselves with a valid User-Agent / Referer, rate-limits traffic, and
forbids heavy or bulk use. It’s fine for a personal map or a quick prototype; for anything in
production or with real traffic, use a dedicated tile provider — which you grant exactly the same
way (add its tile host as an image host).