Restore theme assets — CSP derived the wrong host and SVG was disabled

Fixkamo-internal
Shipped
August 3, 2026 at 3:56 AM UTC
Author
kamo
Commit
aa7c32d

Avatars, org logos and backgrounds stopped loading for every tenant. Two separate regressions I introduced in 36ad904b, both live for hours. 1. The per-request img-src policy derived the tenant domain from `request.nextUrl.hostname`. Inside the pod that is 127.0.0.1, so taking the last two labels produced the apex "0.0" and the emitted header was: img-src 'self' data: blob: https://theme.0.0 https://*.0.0 Every real theme.<domain> origin was therefore blocked. The host has to come from the forwarded headers — requests arrive through Traefik and the gateway, so the external hostname survives only there. The rest of this codebase already knew that; the API proxy forwards X-Forwarded-Host explicitly so backends can build theme URLs from it. The deeper mistake was failing CLOSED on a value it could not parse. A policy built from a nonsense apex is indistinguishable from a strict one at the server, so nothing looked wrong from the outside — it just silently blocked images everywhere. tenantApex() now returns null for anything that is not a registrable domain (IP literal, bare label, localhost, numeric TLD) and the caller omits the header entirely. A missing header is the previous behaviour; a wrong header is an outage. 2. dangerouslyAllowSVG: false blocked SVG through the optimizer for ALL sources, not only remote ones — and the org/software logos and the provider icons under /logo are SVG. Re-enabled, and it is much narrower now than when it was first set: remotePatterns is empty, so the optimizer cannot be aimed at a foreign host at all, and external images go through /api/images/proxy, which validates content-type and serves with `default-src 'none'; sandbox` plus nosniff. Tests cover the derivation against the exact input that caused this, the white-label domains, forwarded-host precedence, comma-joined forwarded values, ports, and every shape that must yield null.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing