The hotel moved from .nitro to .hab bundles, so the imager must treat .hab like .nitro and the public avatar endpoints must accept the figure strings the client sends (including extra trailing segments such as `.0`, which the old FIGURE_RE rejected with a 400). - imager-upstream: relax FIGURE_RE, extend parseAvatarQuery test coverage - api/imaging/avatar + /imaging: shared validation, placeholder and ETag/304 - api/imaging/badge: single-flight upstream fetch and conditional responses - imager-http/imager-png: strong ETag helpers and APNG passthrough guard - csp + next/image: unoptimized external images, tightened CSP - deps: override postcss-selector-parser to ^7.1.6 - also fold in the pending drizzle draft snapshot and stray test cleanup
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
/**
|
|
* Build a Content-Security-Policy value.
|
|
* Scripts/styles: per-request nonce for Next.js and ThemeVars inline tags.
|
|
* style-src-attr keeps 'unsafe-inline' so React `style={{…}}` attributes work.
|
|
*/
|
|
export function buildContentSecurityPolicy(nonce: string): string {
|
|
const isDev = process.env.NODE_ENV === "development";
|
|
const scriptSrc = [
|
|
"'self'",
|
|
`'nonce-${nonce}'`,
|
|
"https://challenges.cloudflare.com",
|
|
"https://www.google.com/recaptcha/",
|
|
"https://www.gstatic.com/recaptcha/",
|
|
"https://static.cloudflareinsights.com",
|
|
...(isDev ? ["'unsafe-eval'"] : []),
|
|
].join(" ");
|
|
|
|
const styleSrc = [
|
|
"'self'",
|
|
"'unsafe-inline'",
|
|
"https://fonts.googleapis.com",
|
|
].join(" ");
|
|
|
|
return [
|
|
"default-src 'self'",
|
|
`script-src ${scriptSrc}`,
|
|
`style-src ${styleSrc}`,
|
|
"style-src-attr 'unsafe-inline'",
|
|
"img-src 'self' data: blob: https:",
|
|
"frame-src 'self' https://challenges.cloudflare.com https://www.google.com/recaptcha/",
|
|
// Clickjacking defence that also covers the `frame-ancestors`-aware
|
|
// browsers X-Frame-Options cannot reach. `upgrade-insecure-requests` is
|
|
// production-only: over plain-HTTP localhost it would rewrite same-origin
|
|
// asset URLs to https and break the dev server.
|
|
"frame-ancestors 'none'",
|
|
"connect-src 'self' https: wss:",
|
|
"font-src 'self' data: https://fonts.gstatic.com",
|
|
"object-src 'none'",
|
|
"base-uri 'self'",
|
|
"form-action 'self'",
|
|
...(isDev ? [] : ["upgrade-insecure-requests"]),
|
|
].join("; ");
|
|
}
|
|
|
|
export function createCspNonce(): string {
|
|
return Buffer.from(crypto.randomUUID()).toString("base64");
|
|
}
|