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
- Add the default-scoped resources to the element/attribute kinds (or vice versa) so every overriding scope allows what it needs
- Remove the redundant default resources if the specific kinds fully cover usage
- 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
- Declare each scope explicitly instead of relying on default inheritance
- Mirror allowlist entries into elem/attr kinds whenever you add them
- Test the final CSP header in devtools against the resources each scope actually loads
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
- Shiki syntax highlighting uses inline styles that are not co
- context.csp was used when rendering the route ${colors.green
- A resource was added to `${specific}`, but `${general}` also
- EnvPrefixConflictsWithSecret
- Auto-generating collections for folders in "src/content/" t
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/22d8be15a16d3d0d.
Report an issue: GitHub.