Svelte cannot produe safe CSP for default build / any inline styles
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 20.8k
- Forks
- 2.3k
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 156
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the issue with the default scaffold, the shown svelte.config.js style-src directive, and app.html, then run the build and preview commands. Trace how SvelteKit handles the inline display: contents style and CSP hashes; done means the default app builds and previews without a style-src violation under the restrictive policy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- build-system, security, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100