Skip to content

Commit c022254

Browse files
committed
feat: stabilise CSP
1 parent 170f64e commit c022254

File tree

17 files changed

+327
-322
lines changed

17 files changed

+327
-322
lines changed

packages/astro/src/assets/fonts/vite-plugin-fonts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
195195
consumableMap = res.consumableMap;
196196

197197
// Handle CSP
198-
if (shouldTrackCspHashes(settings.config.experimental.csp)) {
199-
const algorithm = getAlgorithm(settings.config.experimental.csp);
198+
if (shouldTrackCspHashes(settings.config.security.csp)) {
199+
const algorithm = getAlgorithm(settings.config.security.csp);
200200

201201
// Generate a hash for each style we generate
202202
for (const { css } of internalConsumableMap.values()) {

packages/astro/src/core/build/generate.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ async function generatePath(
667667

668668
if (
669669
pipeline.settings.adapter?.adapterFeatures?.experimentalStaticHeaders &&
670-
pipeline.settings.config.experimental?.csp
670+
pipeline.settings.config.security?.csp
671671
) {
672672
routeToHeaders.set(pathname, { headers: responseHeaders, route: integrationRoute });
673673
}
@@ -717,14 +717,14 @@ async function createBuildManifest(
717717
};
718718
}
719719

720-
if (shouldTrackCspHashes(settings.config.experimental.csp)) {
721-
const algorithm = getAlgorithm(settings.config.experimental.csp);
720+
if (shouldTrackCspHashes(settings.config.security.csp)) {
721+
const algorithm = getAlgorithm(settings.config.security.csp);
722722
const scriptHashes = [
723-
...getScriptHashes(settings.config.experimental.csp),
723+
...getScriptHashes(settings.config.security.csp),
724724
...(await trackScriptHashes(internals, settings, algorithm)),
725725
];
726726
const styleHashes = [
727-
...getStyleHashes(settings.config.experimental.csp),
727+
...getStyleHashes(settings.config.security.csp),
728728
...settings.injectedCsp.styleHashes,
729729
...(await trackStyleHashes(internals, settings, algorithm)),
730730
];
@@ -734,12 +734,12 @@ async function createBuildManifest(
734734
? 'adapter'
735735
: undefined,
736736
styleHashes,
737-
styleResources: getStyleResources(settings.config.experimental.csp),
737+
styleResources: getStyleResources(settings.config.security.csp),
738738
scriptHashes,
739-
scriptResources: getScriptResources(settings.config.experimental.csp),
739+
scriptResources: getScriptResources(settings.config.security.csp),
740740
algorithm,
741741
directives: getDirectives(settings),
742-
isStrictDynamic: getStrictDynamic(settings.config.experimental.csp),
742+
isStrictDynamic: getStrictDynamic(settings.config.security.csp),
743743
};
744744
}
745745
return {

packages/astro/src/core/build/plugins/plugin-manifest.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,14 @@ async function buildManifest(
321321

322322
let csp: SSRManifestCSP | undefined = undefined;
323323

324-
if (shouldTrackCspHashes(settings.config.experimental.csp)) {
325-
const algorithm = getAlgorithm(settings.config.experimental.csp);
324+
if (shouldTrackCspHashes(settings.config.security.csp)) {
325+
const algorithm = getAlgorithm(settings.config.security.csp);
326326
const scriptHashes = [
327-
...getScriptHashes(settings.config.experimental.csp),
327+
...getScriptHashes(settings.config.security.csp),
328328
...(await trackScriptHashes(internals, settings, algorithm)),
329329
];
330330
const styleHashes = [
331-
...getStyleHashes(settings.config.experimental.csp),
331+
...getStyleHashes(settings.config.security.csp),
332332
...settings.injectedCsp.styleHashes,
333333
...(await trackStyleHashes(internals, settings, algorithm)),
334334
];
@@ -338,12 +338,12 @@ async function buildManifest(
338338
? 'adapter'
339339
: undefined,
340340
scriptHashes,
341-
scriptResources: getScriptResources(settings.config.experimental.csp),
341+
scriptResources: getScriptResources(settings.config.security.csp),
342342
styleHashes,
343-
styleResources: getStyleResources(settings.config.experimental.csp),
343+
styleResources: getStyleResources(settings.config.security.csp),
344344
algorithm,
345345
directives: getDirectives(settings),
346-
isStrictDynamic: getStrictDynamic(settings.config.experimental.csp),
346+
isStrictDynamic: getStrictDynamic(settings.config.security.csp),
347347
};
348348
}
349349

packages/astro/src/core/config/schemas/base.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export const ASTRO_CONFIG_DEFAULTS = {
8989
security: {
9090
checkOrigin: true,
9191
allowedDomains: [],
92+
csp: false,
9293
},
9394
env: {
9495
schema: {},
@@ -99,7 +100,6 @@ export const ASTRO_CONFIG_DEFAULTS = {
99100
experimental: {
100101
clientPrerender: false,
101102
contentIntellisense: false,
102-
csp: false,
103103
chromeDevtoolsWorkspace: false,
104104
svgo: false,
105105
},
@@ -428,6 +428,29 @@ export const AstroConfigSchema = z.object({
428428
)
429429
.optional()
430430
.default(ASTRO_CONFIG_DEFAULTS.security.allowedDomains),
431+
csp: z
432+
.union([
433+
z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.security.csp),
434+
z.object({
435+
algorithm: cspAlgorithmSchema,
436+
directives: z.array(allowedDirectivesSchema).optional(),
437+
styleDirective: z
438+
.object({
439+
resources: z.array(z.string()).optional(),
440+
hashes: z.array(cspHashSchema).optional(),
441+
})
442+
.optional(),
443+
scriptDirective: z
444+
.object({
445+
resources: z.array(z.string()).optional(),
446+
hashes: z.array(cspHashSchema).optional(),
447+
strictDynamic: z.boolean().optional(),
448+
})
449+
.optional(),
450+
}),
451+
])
452+
.optional()
453+
.default(ASTRO_CONFIG_DEFAULTS.security.csp),
431454
})
432455
.optional()
433456
.default(ASTRO_CONFIG_DEFAULTS.security),
@@ -478,29 +501,6 @@ export const AstroConfigSchema = z.object({
478501
.optional()
479502
.default(ASTRO_CONFIG_DEFAULTS.experimental.contentIntellisense),
480503
fonts: z.array(z.union([localFontFamilySchema, remoteFontFamilySchema])).optional(),
481-
csp: z
482-
.union([
483-
z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.csp),
484-
z.object({
485-
algorithm: cspAlgorithmSchema,
486-
directives: z.array(allowedDirectivesSchema).optional(),
487-
styleDirective: z
488-
.object({
489-
resources: z.array(z.string()).optional(),
490-
hashes: z.array(cspHashSchema).optional(),
491-
})
492-
.optional(),
493-
scriptDirective: z
494-
.object({
495-
resources: z.array(z.string()).optional(),
496-
hashes: z.array(cspHashSchema).optional(),
497-
strictDynamic: z.boolean().optional(),
498-
})
499-
.optional(),
500-
}),
501-
])
502-
.optional()
503-
.default(ASTRO_CONFIG_DEFAULTS.experimental.csp),
504504
chromeDevtoolsWorkspace: z
505505
.boolean()
506506
.optional()

packages/astro/src/core/csp/common.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { BuildInternals } from '../build/internal.js';
99
import { generateCspDigest } from '../encryption.js';
1010
import type { CspDirective } from './config.js';
1111

12-
type EnabledCsp = Exclude<AstroConfig['experimental']['csp'], false>;
12+
type EnabledCsp = Exclude<AstroConfig['security']['csp'], false>;
1313

1414
export function shouldTrackCspHashes(csp: any): csp is EnabledCsp {
1515
return csp === true || typeof csp === 'object';
@@ -55,7 +55,7 @@ export function getStyleResources(csp: EnabledCsp): string[] {
5555
// because it has to collect and deduplicate font resources from both the user
5656
// config and the vite plugin for fonts
5757
export function getDirectives(settings: AstroSettings): CspDirective[] {
58-
const { csp } = settings.config.experimental;
58+
const { csp } = settings.config.security;
5959
if (!shouldTrackCspHashes(csp)) {
6060
return [];
6161
}

packages/astro/src/core/dev/restart.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ async function restartContainer(container: Container): Promise<Container | Error
7777

7878
try {
7979
const { astroConfig } = await resolveConfig(container.inlineConfig, 'dev', container.fs);
80-
if (astroConfig.experimental.csp) {
80+
if (astroConfig.security.csp) {
8181
logger.warn(
8282
'config',
8383
"Astro's Content Security Policy (CSP) does not work in development mode. To verify your CSP implementation, build the project and run the preview server.",
@@ -125,7 +125,7 @@ export async function createContainerWithAutomaticRestart({
125125
}: CreateContainerWithAutomaticRestart): Promise<Restart> {
126126
const logger = createNodeLogger(inlineConfig ?? {});
127127
const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, 'dev', fs);
128-
if (astroConfig.experimental.csp) {
128+
if (astroConfig.security.csp) {
129129
logger.warn(
130130
'config',
131131
"Astro's Content Security Policy (CSP) does not work in development mode. To verify your CSP implementation, build the project and run the preview server.",

packages/astro/src/core/errors/errors-data.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,12 +1410,12 @@ export const FontFamilyNotFound = {
14101410
* @description
14111411
* The CSP feature isn't enabled
14121412
* @message
1413-
* The `experimental.csp` configuration isn't enabled.
1413+
* The `security.csp` configuration isn't enabled.
14141414
*/
14151415
export const CspNotEnabled = {
14161416
name: 'CspNotEnabled',
14171417
title: "CSP feature isn't enabled",
1418-
message: "The `experimental.csp` configuration isn't enabled.",
1418+
message: "The `security.csp` configuration isn't enabled.",
14191419
} satisfies ErrorData;
14201420

14211421
/**

packages/astro/src/types/astro.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export type SerializedRouteData = Omit<
2929
};
3030
};
3131

32-
type CspObject = Required<Exclude<AstroConfig['experimental']['csp'], boolean>>;
32+
type CspObject = Required<Exclude<AstroConfig['security']['csp'], boolean>>;
3333

3434
export interface AstroSettings {
3535
config: AstroConfig;

0 commit comments

Comments
 (0)