diff --git a/.changeset/early-bees-write.md b/.changeset/early-bees-write.md new file mode 100644 index 000000000000..2a8175948b60 --- /dev/null +++ b/.changeset/early-bees-write.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes an issue where `report-uri` wasn't available in `experimental.csp.directives`, causing a typing error and a runtime validation error. diff --git a/.changeset/shaggy-singers-argue.md b/.changeset/shaggy-singers-argue.md new file mode 100644 index 000000000000..b61fac02693e --- /dev/null +++ b/.changeset/shaggy-singers-argue.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes a type error for the CSP directives `upgrade-insecure-requests`, `sandbox`, and `trusted-type`. diff --git a/packages/astro/src/core/csp/config.ts b/packages/astro/src/core/csp/config.ts index 975cb0afc77c..b33055816e11 100644 --- a/packages/astro/src/core/csp/config.ts +++ b/packages/astro/src/core/csp/config.ts @@ -57,6 +57,7 @@ const ALLOWED_DIRECTIVES = [ 'object-src', 'referrer', 'report-to', + 'report-uri', 'require-trusted-types-for', 'sandbox', 'trusted-types', @@ -64,7 +65,7 @@ const ALLOWED_DIRECTIVES = [ 'worker-src', ] as const; type AllowedDirectives = (typeof ALLOWED_DIRECTIVES)[number]; -export type CspDirective = `${AllowedDirectives} ${string}`; +export type CspDirective = `${AllowedDirectives}${string | undefined}`; export const allowedDirectivesSchema = z.custom((value) => { if (typeof value !== 'string') { diff --git a/packages/astro/test/csp.test.js b/packages/astro/test/csp.test.js index e5af9ef28983..c79740aace81 100644 --- a/packages/astro/test/csp.test.js +++ b/packages/astro/test/csp.test.js @@ -231,6 +231,31 @@ describe('CSP', () => { assert.ok(meta.attr('content').toString().includes("'strict-dynamic';")); }); + it("allows the use of directives that don't require values, and deprecated ones", async () => { + fixture = await loadFixture({ + root: './fixtures/csp/', + experimental: { + csp: { + directives: [ + 'upgrade-insecure-requests', + 'sandbox', + 'trusted-types', + 'report-uri https://endpoint.example.com', + ], + }, + }, + }); + await fixture.build(); + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + const meta = $('meta[http-equiv="Content-Security-Policy"]'); + assert.ok(meta.attr('content').toString().includes('upgrade-insecure-requests')); + assert.ok(meta.attr('content').toString().includes('sandbox')); + assert.ok(meta.attr('content').toString().includes('trusted-types')); + assert.ok(meta.attr('content').toString().includes('report-uri https://endpoint.example.com')); + }); + it('should serve hashes via headers for dynamic pages, when the strategy is "auto"', async () => { fixture = await loadFixture({ root: './fixtures/csp-adapter/',