Skip to content

CSP: Cannot set 'unsafe-inline' with 'strict-dynamic' CSP (i.e. with strict CSP) #15166

@rishvic

Description

@rishvic

Describe the bug

When implementing strict CSP, many resources (web.dev, sample safe policy in CSP Evaluator) suggest adding 'unsafe-inline' along with 'strict-dynamic' and 'nonce-{random}' directives, so that older browsers without strict CSP support still work (note that modern browsers which support strict CSP ignore 'unsafe-inline' in such cases, causing no downgrade in security). But if I try adding both nonce based strict CSP and 'unsafe-inline' inside the configuration, the 'nonce-{random}' directive goes missing, resulting in strict CSP not working as intended.

Reproduction

https://github.com/rishvic/sveltekit-no-strict-csp-with-fallback contains the changes required on the minimal SvelteKit template that are needed to reproduce the issue with nonce-based strict CSP. To reproduce the issue, run the following commands:

# 1. Clone the repository.
git clone https://github.com/rishvic/sveltekit-no-strict-csp-with-fallback.git
cd sveltekit-no-strict-csp-with-fallback

# 2. Run the prod build.
pnpm install
pnpm build && pnpm preview

# 3. Inspect the CSP headers served by the page.
curl -I http://localhost:4173

Note the lack of 'nonce-{random}' directive in the content-security-policy header in the response:

...
content-security-policy: script-src 'strict-dynamic' 'unsafe-inline'
...

Logs

Entire output of the curl program:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
content-length: 3133
content-security-policy: script-src 'strict-dynamic' 'unsafe-inline'
content-type: text/html
etag: "1oi7iqa"
link: <./_app/immutable/entry/start.Db8VV5Jv.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/BrAptPyQ.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/B2ZnbzTz.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/DFNtM6XN.js>; rel="modulepreload"; nopush, <./_app/immutable/entry/app.D9BRVT7u.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/DlY8NuG-.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/CNKBvEPn.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/6iBK7G8E.js>; rel="modulepreload"; nopush, <./_app/immutable/nodes/0.DGSOzYzj.js>; rel="modulepreload"; nopush, <./_app/immutable/nodes/2.JSQqfXsN.js>; rel="modulepreload"; nopush, <./_app/immutable/chunks/yHXKBK-D.js>; rel="modulepreload"; nopush
x-sveltekit-page: true
Date: Wed, 14 Jan 2026 19:42:52 GMT
Connection: keep-alive
Keep-Alive: timeout=5

System Info

System:
    OS: Linux 6.18 Arch Linux
    CPU: (16) x64 AMD Ryzen 7 5800HS with Radeon Graphics
    Memory: 10.92 GB / 15.03 GB
    Container: Yes
    Shell: 5.9 - /usr/bin/zsh
  Binaries:
    Node: 24.12.0 - /usr/bin/node
    Yarn: 1.22.22 - /home/rishvic/.local/bin/yarn
    npm: 11.7.0 - /usr/bin/npm
    pnpm: 10.26.1 - /home/rishvic/.local/bin/pnpm
  Browsers:
    Chromium: 143.0.7499.169
    Firefox: 146.0.1
    Firefox Developer Edition: 146.0.1
  npmPackages:
    @sveltejs/adapter-auto: ^7.0.0 => 7.0.0 
    @sveltejs/kit: ^2.49.1 => 2.49.4 
    @sveltejs/vite-plugin-svelte: ^6.2.1 => 6.2.4 
    svelte: ^5.45.6 => 5.46.3 
    vite: ^7.2.6 => 7.3.1

Severity

annoyance

Additional Information

The issue should be considered fixed imo when allowed to add 'unsafe-inline' along with strict CSP.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions