Files
EpicNext-Cms/src/lib/csp.ts
T
SimoandCursor 2ff08e5127
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 1m35s
chore: patch deps, CSP style nonces, otplib 13, and PR CI
Co-authored-by: Cursor <[email protected]>
2026-07-21 20:46:02 +02:00

43 lines
1.2 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",
"https://cdn.jsdelivr.net",
...(isDev ? ["'unsafe-eval'"] : []),
].join(" ");
const styleSrc = [
"'self'",
`'nonce-${nonce}'`,
"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/",
"connect-src 'self' https: wss:",
"font-src 'self' data: https://fonts.gstatic.com",
"object-src 'none'",
"base-uri 'self'",
"form-action 'self'",
].join("; ");
}
export function createCspNonce(): string {
return Buffer.from(crypto.randomUUID()).toString("base64");
}