critical: CSP header doesn't like hashed onload attribute

When I use Critical, I end up with this HTML link element after the inlined styles:

<link rel="stylesheet" href="/css/main.css" media="print" onload="this.media='all'">

And this when it’s minified in production:

<link href=/css/main.min.css rel=stylesheet media=print onload='this.media="all"'>

I’m using a Content Security Policy header with script-src 'self';, and of course the onload inline script throws a browser console error.

So I’ve tried hashing this.media="all" (with double quotes) and adding 'sha256-kx8Md/dUVxiWxH0xNDfI+0jY+S4Ev2Jri3jBG4rrm9E=' to the script-src directive. The same console error is thrown.

I’ve also tried instead hashing this.media='all' (with single quotes) and adding 'sha256-MhtPZXr7+LpJUY5qtMutB+qWfQtMaPccfe7QXtCcEYc=' to the script-src directive. Same console error.

Has anyone managed to use Critical along with a secure CSP header that works with the onload attribute (without using unsafe-inline)?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 24

Most upvoted comments

Yes, this is what I was getting at. It’s a shame to need to choose between having (1) asyncronously loaded stylesheets, or (2) a secure CSP.

Security and performance are both very important, but in this case I feel security wins out over performance: I’d rather have a secure CSP than asyncronously loaded stylesheets.

But I’d much rather have both. 😭

@paulshryock may i suggest using this approach: rel="stylesheet preload"? This should be valid html, that is not violating CSP that hopefully, isn’t blocking css. https://www.sitepoint.com/critical-rendering-path-css-fast-loading-website/ I sadly lack the experience to properly test this, but alas maybe you can have a go with it 😃.

Yeah, I may end up going with something like this instead of the way critical loads stylesheets after the DOM load event. It’s a shame, because I think the inline JS is a great solution (if it worked with CSP).

True, but if rel=“stylesheet preload” is equally good in fuctionality as the DOM load event. Then it’s feasible to add a --preload flag or --onload flag to criticalcss. So that users can pick what suites their needs

Use onload to support older browsers like IE. Use preload to have none violating CSP.

Curious what @bezoerb thinks about this proposal.

ah i see, so there isn’t a easy way to preload withoud causing csp to act up?

It should given the REL spec: https://stackoverflow.com/questions/19185431/can-you-have-two-values-in-a-single-rel-attribute

Also, you can test our site: https://voxsiren.net/ to see if there’s any difference. I think you can test it by loading a big CSS file and try loading two css files with both preload and one withoud. You can then compare how they are loaded and see if preloading this way works.

Hope you can verify it’s workings

Ah, so skipping the onload handler. Yeah, that makes sense.