first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
# Strict Content-Security-Policy for the Scalar UI shell
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
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
```ts
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.