Skip to content

Svelte cannot produe safe CSP for default build / any inline styles #11747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
atjn opened this issue Jan 27, 2024 · 5 comments
Open

Svelte cannot produe safe CSP for default build / any inline styles #11747

atjn opened this issue Jan 27, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@atjn
Copy link

atjn commented Jan 27, 2024

Describe the bug

Hello and thank you all for making and maintaining Svelte ❤️

This is related to #5215, but that seems to be specifically targeted at the animations API, whereas I am talking about a broader issue.

In the svelte.config.js file, when you define the Content Security Policy script-src: 'self', and try to build your project with inline scripts, Svelte is fairly good at detecting the inline scripts and adding hashes to the CSP to make sure they can be loaded in the browser.

On the other hand, if you define style-src: 'self', it does not seem like Svelte makes any effort to produce hashes for inline styles. This means you either cannot have any inline styles, or you must make your CSP unsafe by defining unsafe-inline.

Personally, I can live with the first option where I never define inline styles, but the problem is that Svelte itself defines an inline style in the default app.html:

<body data-sveltekit-preload-data="hover">
  <div style="display: contents">%sveltekit.body%</div>
</body>

I certainly could work around this by removing this style and moving it to an imported global stylesheet, but it seems a bit hacky to me, and I would really prefer to just use the default Svelte config, which I know is well thought out and works well with Svelte (except in this case lol).

Reproduction

Scaffold a new SvelteKit project by running npm create svelte@latest my-app

Then choose the Skeleton project with default settings:

create-svelte version 6.0.8

┌  Welcome to SvelteKit!
│
◇  Which Svelte app template?
│  Skeleton project
│
◇  Add type checking with TypeScript?
│  Yes, using JavaScript with JSDoc comments
│
◇  Select additional options (use arrow keys/space bar)
│  none
│
└  Your project is ready!

Run npm install && npm run build && npm run preview -- --open and observe that the app works as intended with no errors in the console.

Now restrict the style-src CSP directive in your svelte.config.js file, so that it looks like this:

const config = {
  kit: {
    adapter: adapter(),
    csp: {
      directives: {
        "default-src": ["*"],
        "style-src": ["self"],
      },
    },
  }
};

Run npm run build && npm run preview -- --open and observe that the browser logs a CSP violation. In Firefox, the message is:

Content-Security-Policy: The page’s settings blocked the loading of a resource at inline (“style-src”).
Source: display: contents

Logs

No response

System Info

System:
    OS: Linux
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 20.11.0 - ~/.asdf/installs/nodejs/20.11.0/bin/node
    npm: 10.3.0 - ~/.asdf/plugins/nodejs/shims/npm
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.1.1 
    @sveltejs/kit: ^2.0.0 => 2.5.0 
    @sveltejs/vite-plugin-svelte: ^3.0.0 => 3.0.1 
    svelte: ^4.2.7 => 4.2.9

Severity

serious, but I can work around it

Additional Information

If possible, I think the best solution to this problem would be for Svelte to detect all inline styles in a page, move them to a single <style> tag in the header, then produce a hash/nonce for that tag and add it to the CSP.

I think the minimum viable solution is to change the default scaffolding to use some sort of global stylesheet. That would allow people like me to use Svelte and CSP because we don't use inline styles. But it would not address any use case that needs inline styles.

@nilsborg
Copy link

nilsborg commented Apr 22, 2024

Yes I can confirm this. Also working on a project which needs to support a certain level of CSP rules and currently I can see no way to get that done with out allowing unsafe-inline.. is this something that will be easier with Svelte 5?

@gregg-cbs
Copy link

I can confirm when looking into CSP i found it difficult to do it with Sveltekit and I gave up. Not to throw sand into svelte devs eyes but in nextjs its easy manage CSP so i would think we can improve it in svelte.

@SGupta-Nagarro
Copy link

SGupta-Nagarro commented Jul 11, 2024

Workaround -->

<div class="display-s" id="svelte">%sveltekit.body%</div>

and make css -->

.display-s {
	display: contents
}

@eltigerchino eltigerchino added the bug Something isn't working label Nov 20, 2024
@jornfranke
Copy link

jornfranke commented Feb 19, 2025

Unfortunately this is not a full workaround. While it allows to load the page, you will soon see the following message:

Content-Security-Policy: The page’s settings blocked an inline style (style-src-attr) from being applied because it violates the following directive: “style-src 'self'”

It comes from a file disclose-version.*.js:1:2637

It seems to also leads that svelte writes at the end of the page "untitled page".
edit: this seems to come from id="svelte-announcer"

<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="">untitled page<!----></div>

If I add to the CSP for style-src unsafe-inline it works.

Any idea how to resolve/troubleshoot this are welcome.

@jornfranke
Copy link

See linked issue for a resolution - the svelte-announcer uses inline-style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

6 participants