withastro/astro · warning

`security.csp.${name}Directive` defines `${name}-src` resour

Error message

`security.csp.${name}Directive` defines `${name}-src` resources (${sources.default.resources.join(' ')}) as well as ${shadowed.join(' and ')} resources or hashes. Because ${shadowed.join(' and ')} override `${name}-src` for their scope (browsers do not fall back), those `${name}-src` resources will not apply there. Add them to the corresponding `kind` if needed.

What it means

A scriptDirective/styleDirective can declare sources at three scopes: default (`${name}-src`), element (`${name}-src-elem`) and attribute (`${name}-src-attr`). CSP semantics make the elem/attr directives override the generic one for their scope with no browser fallback, so resources listed only under `default` never apply where an elem/attr entry exists. Astro warns (domain 'csp') when a directive mixes default resources with element/attribute entries so you can copy anything needed into the specific kind.

Source

Thrown at packages/astro/src/core/messages/runtime.ts:453

		{ name: 'style', directive: csp.styleDirective },
	] as const;

	for (const { name, directive } of families) {
		const sources = partitionByKind({
			resources: directive?.resources ?? [],
			hashes: directive?.hashes ?? [],
		});
		if (sources.default.resources.length === 0) continue;
		const shadowed: string[] = [];
		if (sources.element.resources.length > 0 || sources.element.hashes.length > 0) {
			shadowed.push(`\`${name}-src-elem\``);
		}
		if (sources.attribute.resources.length > 0 || sources.attribute.hashes.length > 0) {
			shadowed.push(`\`${name}-src-attr\``);
		}
		if (shadowed.length === 0) continue;

		logger.warn(
			'csp',
			`\`security.csp.${name}Directive\` defines \`${name}-src\` resources (${sources.default.resources.join(
				' ',
			)}) as well as ${shadowed.join(' and ')} resources or hashes. Because ${shadowed.join(
				' and ',
			)} override \`${name}-src\` for their scope (browsers do not fall back), those \`${name}-src\` resources will not apply there. Add them to the corresponding \`kind\` if needed.`,
		);
	}
}

View on GitHub (pinned to 52e6c34790)

Solutions

  1. Add the default-scoped resources to the element/attribute kinds (or vice versa) so every overriding scope allows what it needs
  2. Remove the redundant default resources if the specific kinds fully cover usage
  3. Keep only the default entry when you do not need elem/attr overrides at all

Example fix

// astro.config.mjs — before
security: {
  csp: {
    scriptDirective: {
      resources: ['https://cdn.example.com'],
      element: { resources: ['https://analytics.test'] },
    },
  },
},

// after — cdn also allowed where element scope overrides
scriptDirective: {
  resources: ['https://cdn.example.com'],
  element: { resources: ['https://analytics.test', 'https://cdn.example.com'] },
},
Defensive patterns

Strategy: validation

Validate before calling

function findShadowedDirectives(directive) {
  const shadowed = [];
  if ((directive.element?.resources?.length ?? directive.element?.hashes?.length ?? 0) > 0) shadowed.push('element');
  if ((directive.attribute?.resources?.length ?? directive.attribute?.hashes?.length ?? 0) > 0) shadowed.push('attribute');
  return directive.resources?.length ? shadowed : [];
}
// fail a config-lint step when findShadowedDirectives(...) is non-empty

Type guard

function hasShadowedDefaults(d): d is { resources: string[]; element?: object; attribute?: object } {
  return Array.isArray(d.resources) && d.resources.length > 0 &&
    (hasEntries(d.element) || hasEntries(d.attribute));
}

Prevention

When it happens

Trigger: security.csp.scriptDirective or styleDirective configured with resources at the default level plus a non-empty element and/or attribute entry (resources or hashes), e.g. { resources: ['https://cdn.example.com'], element: { resources: ['https://a.test'] } }.

Common situations: Tightening CSP for script tags without realizing script-src-elem no longer inherits script-src; adding hashes for inline event handlers next to a default allowlist; translating a raw CSP header into Astro's structured directives.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/22d8be15a16d3d0d. Report an issue: GitHub.