Document CSP directive rationale and strengthen inline-script assertion
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,11 +42,13 @@ describe('buildSecurityHeaders', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not allow inline scripts', () => {
|
it('does not allow inline scripts', () => {
|
||||||
expect(headers['Content-Security-Policy']).not.toContain("'unsafe-inline' 'nonce-");
|
// Script directive must not include 'unsafe-inline' — find it explicitly and assert.
|
||||||
const scriptDirective = headers['Content-Security-Policy']
|
const scriptDirective = headers['Content-Security-Policy']
|
||||||
.split(';')
|
.split(';')
|
||||||
.map(s => s.trim())
|
.map(s => s.trim())
|
||||||
.find(s => s.startsWith('script-src')) ?? '';
|
.find(s => s.startsWith('script-src')) ?? '';
|
||||||
|
expect(scriptDirective).toContain("'self'");
|
||||||
expect(scriptDirective).not.toContain("'unsafe-inline'");
|
expect(scriptDirective).not.toContain("'unsafe-inline'");
|
||||||
|
expect(scriptDirective).not.toContain("'unsafe-eval'");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ export function buildSecurityHeaders(): Record<string, string> {
|
|||||||
const csp = [
|
const csp = [
|
||||||
"default-src 'self'",
|
"default-src 'self'",
|
||||||
"img-src 'self' data:",
|
"img-src 'self' data:",
|
||||||
|
// Astro's scoped-style system injects inline style attributes at build time;
|
||||||
|
// 'unsafe-inline' here is required until we migrate to a hash/nonce strategy.
|
||||||
"style-src 'self' 'unsafe-inline'",
|
"style-src 'self' 'unsafe-inline'",
|
||||||
"font-src 'self'",
|
"font-src 'self'",
|
||||||
"script-src 'self'",
|
"script-src 'self'",
|
||||||
"connect-src 'self'",
|
"connect-src 'self'",
|
||||||
"frame-ancestors 'none'",
|
"frame-ancestors 'none'",
|
||||||
"base-uri 'self'",
|
"base-uri 'self'",
|
||||||
|
// No forms on this marketing site today (all auth redirects go to auth.cameleer.io
|
||||||
|
// as plain <a> navigations). If a future form is added, relax to 'self' or an allow-list.
|
||||||
"form-action 'none'",
|
"form-action 'none'",
|
||||||
"object-src 'none'",
|
"object-src 'none'",
|
||||||
].join('; ');
|
].join('; ');
|
||||||
|
|||||||
Reference in New Issue
Block a user