Skip to content

SvelteKit adds unwanted CSP nonce / hash entries automatically when inlineStyleThreshold is used #9368

Closed
@lietu

Description

@lietu

Preface

It's incredibly common for things on the internet to rely on inline styles. This is now even documented on SvelteKit's own documentation as something Svelte requires for proper function. In practice many 3rd party scripts, say payment gateways, more explicitly Paddle.js depend on inline styles to display e.g. payment overlays for your users. The app.html template also includes style="display: contents;"

When a Content-Security-Policy for a category (e.g. style-src) includes a hash/nonce, the 'unsafe-inline' option is conveniently .. ignored .. by browsers. This would break things like Svelte transitions, templates with inline styles, component libraries that use them, and your payment overlays or other 3rd party scripts that depend on inline styles.

Describe the bug

When using SvelteKit, it occasionally decides to inject some nonce/sha to the style-src even though it was explicitly told the configuration for it, and even though it already contains the 'unsafe-inline' -option. This breaks the 'unsafe-inline' option, which breaks Svelte, the SvelteKit template, e.g. Carbon Components Svelte (which has many inline styles), and payment gateway integrations - like Paddle.

This SEEMS TO happen when the inlineStyleThreshold is used, at least on the @sveltejs/adapter-node, at least that's the way I can reproduce it for now. I dunno if there are other triggers.

The options for csp.mode are hash, nonce, and auto, which switches between hash and nonce depending on some circumstances. There is no none option to disable adding hashes or nonces. That's probably good, as far as script tags go, but completely and unquestionably wrong when it goes to style elements and attributes.

Reproduction

https://github.com/lietu/sveltekit-csp-demo

Logs

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'unsafe-inline' 'sha256-Jlo48F6zKLK2XGPcosZ4n5EuEuOwQBrKt/g/FvUQNbE='". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

System Info

System:
    OS: Linux 5.15 Manjaro Linux
    CPU: (24) x64 AMD EPYC-Rome Processor
    Memory: 9.11 GB / 31.34 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 19.6.0 - /usr/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 8.19.2 - /usr/bin/npm
  Browsers:
    Chromium: 110.0.5481.177
    Firefox: 110.0
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.0.0 
    @sveltejs/adapter-node: ^1.2.2 => 1.2.2 
    @sveltejs/kit: ^1.5.0 => 1.11.0 
    svelte: ^3.54.0 => 3.55.1 
    vite: ^4.0.0 => 4.1.4 

Severity

serious, but I can work around it

Additional Information

The only workaround I know of is to disable inlineStyleThreshold which adds a lot of unnecessary requests after the render, which causes particularly unwanted behavior on cold starts of containers on Google Cloud Run.

There's this fun effect where you take e.g. 15 seconds to respond to the first request, then when the browser loads the first screen, it fires off a few dozen other requests to the server, Google Cloud Run sees a lot of requests coming in and starts booting up a second container to process them and that takes another 15 seconds and suddenly it takes double the time to get your content and styles in place. This may be to some extent mitigated by increasing the concurrent request count in GCR but it's not a "fix" .. which is why the inlineStyleThreshold was enabled in the project where this issue popped up.

All in all, you could say suboptimal experience either way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions