Files
skills/docs/api-stack/api/api-openapi-ui-scalar/src/headers/csp.md
2026-05-29 08:20:56 +01:00

3.0 KiB

Strict Content-Security-Policy for the Scalar UI shell

(no submodules)

Purpose

The headers module builds the Content-Security-Policy header value emitted on every HTML response from the Scalar UI handler. The default posture is conservative: default-src 'self' plus the minimum set of directive relaxations the Scalar shell needs to render. In assetMode = "cdn" the policy is widened (per-handler) to whitelist the configured Scalar CDN origin. In assetMode = "bundled" the policy stays strict — every script/style/font load resolves to the host's own origin under <uiEndpoint>/assets/.

Features

  • buildCspHeader({ assetMode, cdnOrigin?, openapiOrigin? }) — emits the Content-Security-Policy header pair.
  • originOf(url) — extracts the origin portion of a URL or returns undefined for non-URL inputs (used at handler construction to derive the CDN + OpenAPI origins from the parsed options).
  • cspAllowsInlineScripts(headerValue) — conformance predicate the handler test uses to prove the rendered policy never permits inline scripts. The Scalar bootstrap is loaded as an external <script src> so 'unsafe-inline' in script-src would be a regression.
  • 'unsafe-inline' allowed ONLY in style-src for the upstream Scalar React app's runtime style injection.

Usage: Basic

import { buildCspHeader } from "@suaveplan/api-openapi-ui-scalar/headers";

const csp = buildCspHeader({ assetMode: "bundled" });
console.log(csp.name); // "Content-Security-Policy"
console.log(csp.value); // strict "default-src 'self'; script-src 'self'; …"

Usage: Advanced

import {
    buildCspHeader,
    cspAllowsInlineScripts,
    originOf,
} from "@suaveplan/api-openapi-ui-scalar/headers";

const cdnOrigin = originOf("https://cdn.jsdelivr.net/npm/@scalar/api-reference");
const openapiOrigin = originOf("https://api.example.com/openapi.json");
const { name, value } = buildCspHeader({
    assetMode: "cdn",
    cdnOrigin,
    openapiOrigin,
});

if (cspAllowsInlineScripts(value)) {
    throw new Error("Scalar UI must never emit unsafe-inline scripts");
}

API Reference

  • CSP_HEADER_NAME — the canonical header name string.
  • BuildCspInput — { assetMode, cdnOrigin?, openapiOrigin? }.
  • buildCspHeader(input) — { name, value }.
  • originOf(url) — string | undefined.
  • cspAllowsInlineScripts(headerValue) — boolean.

Implementation Notes

The policy structure is built directive-by-directive rather than via a single template string so future per-environment relaxations (e.g. nonce-based script-src) can be added without changing every call site. script-src never includes 'unsafe-inline'; this is a load-bearing invariant enforced by the conformance predicate exposed above. The CDN origin is computed once at handler construction so a malicious cdnUrl value cannot leak into the response header — Zod rejects non-URL inputs at the options layer before originOf runs.