Skip to content
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

CSP Nonce for @html content #7945

Closed
kamerat opened this issue Dec 5, 2022 · 6 comments
Closed

CSP Nonce for @html content #7945

kamerat opened this issue Dec 5, 2022 · 6 comments

Comments

@kamerat
Copy link
Contributor

kamerat commented Dec 5, 2022

Describe the bug

When having stricy-dynamic in the CSP script-src, I am not able to embed code via @html.

Not being able to whitelist domains due to the strict-dynamic makes it hard for me to embed code via @html. When doing so, I get the current error in the console:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http: 'nonce-acY9yNgDa2aOMkqFEISpNw=='". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

Reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-wjps5s?file=src/routes/+page.svelte

Logs

No response

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.14.2 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 7.17.0 - /usr/local/bin/npm
  npmPackages:
    @sveltejs/adapter-node: next => 1.0.0-next.102 
    @sveltejs/kit: ^1.0.0-next.563 => 1.0.0-next.571 
    svelte: ^3.53.1 => 3.53.1 
    vite: ^3.2.4 => 3.2.4

Severity

serious, but I can work around it

Additional Information

No response

@Rich-Harris
Copy link
Member

Two possible solutions off the top of my head:

  • expose nonce via $app/environment:

    <script>
      import { nonce } from '$app/environment';
    </script>
    
    {@html content.replace(/__NONCE__/g, nonce)}

    I don't love this, since it would mean including the nonce in the init <script> block of every server-side render, meaning wasted bytes

  • expose event.nonce on the server

    This would require you to do something like this in handle:

    export function handle({ event, resolve }) {
      return resolve(event, {
        transformPageChunk: ({ html }) => html.replace(/__NONCE__/g, event.nonce)
      });
    }

Of those, the second makes more sense to me. Would this work for your use case? Any other thoughts on the proposed solutions (or others)?

@kamerat
Copy link
Contributor Author

kamerat commented Dec 6, 2022

Thank you for your reply, @Rich-Harris! I do also think this could work.

As the content is comming from a CMS, we would have to add the nonce placeholder on the scripts there in the start.
I could also write a function that auomatically adds the nonce attribute to script tags in the content. However, I'd hope this to be built in to the @html, but I see that this could easily be the opposite of what other people would like as their CSP would be rendered "useless" when using @html.

I have tested both examples of yours;

  • expose nonce via $app/environment:

    SyntaxError: The requested module '/node_modules/@sveltejs/kit/src/runtime/app/environment.js?v=13e3832b' does not provide an export named 'nonce'

  • expose event.nonce on the server

    returns undefined

I tested this in 1.0.0-next.572. Is there something else to be done to make this work? I simply tried your two examples above without any success.

@Rich-Harris
Copy link
Member

Those were API proposals, they haven't been implemented.

To be clear, there's no guarantee that we'll do one of these. Making the nonce easily available is a footgun, since it provides more ways for an attacker to inject malicious content. @dominikg in particular raised some valid concerns about this. We need to carefully consider the pros and cons.

@dominikg
Copy link
Member

dominikg commented Dec 7, 2022

to elaborate, in the stackblitz you are creating a script tag with a link to a third party script, you don't control that server, so it could serve malicious attack scripts tomorrow instead of jquery.
If you added a nonce to that, it's basically equivalent to not having a csp or blanket trusting that source.

Instead you should use a hash to explicitly only trust that exact script. This does not require access to the nonce and keeps protection against changing the script in place. (for jquery and other libraries in particular you should consider self-hosting them instead of pulling them from a 3rd-party cdn)

For content pulled from a cms, it's also dangerous to just add nonces, as again you blindly add trust to something that's out of your control, the security level of that is very similar to unsafe-eval.

@kamerat
Copy link
Contributor Author

kamerat commented Dec 8, 2022

You have a good point @dominikg. CSP has for me been a bumpy ride. It is now clear that from a security standpoint it is better for me to use a hash for the scripts comming from the CMS even tho that it requires manual work each time someone wants to embed something new.

At the time being, this will not be too much work for me, but I do wonder how one keeps track of all of the hashes and their script-counter-part?. For now, I will add a comment next to it, but this only feels like a quick fix - If anyone has a good pattern here, I'd love to hear.

In regards to this issue; I suppose it's up to you guys to have it open or closed. Nevertheless, its's nice that we've had the discussion so that people having the same question can find some information.

Thanks!

@Rich-Harris
Copy link
Member

Closing as Dominik is right, we shouldn't mess around with this stuff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants