with #17 and #20, strict inline styles are supported in principle. It is heavily dependent on the CSS-in-JS framework though, the only one not messing stuff up so far after prerendering is Stitches. emotion and styled-components do in various ways where I see no way yet as you would control/account for that. I conjecture, that in general, the more runtime-heavy the framework is, the less likely it will work.
Remark:Stitches is the tiniest, most minimalist, elegant, fastest, zero-dependency, zero Babel plugins CSS-in-JS package out there and I absolutely love it. I just ported the styles of a website from emotion+twin.macro to stitches+twin.macro and it was fairly easy. Plus some very ugly FOUCs I had with emotion and couldn't get rid of, magically vanished. Better UX + rock-solid CSP to protect against CSS Keylogging. Win Win 😁.
However, there are still inline-style situations this doesn't cover. Sometimes external stuff you can't control adds styles via the HTML style attribute to elements (e.g. the default NextJS 404 page/error components, the optimized responsive image component of DatoCMS, ...)
Possible Solution
Since the inline styles in question are all scattered throughout <body>, the _document drop-ins had to be extended to consider main content that holds the pages prerendered output (go over initialProps.html). Then we could recurse through them and pick up hashes or apply a nonce. However, inline style attributes can't be nonced, and hashed inline styles attributes are only respected style-src 'unsafe-hashes'.
Restriction
Like with styles and scripts handled in <Head>, we can only ever account for what happens during prerendering on the server, anything libs do with styles after hydration is out of control (it is really unfortunate, that the transitive trust propagation of 'strict-dynamic' doesn't apply to style-src - that would've completely solved that problem ).
Possible workaround
You can set style-src-attr 'unsafe-inline'. This will allow unhashed/unnonced inline attribute styles but not inline <style> tags. Maybe that isn't even much of a problem, after all. An actual exploit I know (https://github.com/maxchehab/CSS-Keylogging) wouldn't be possible, since it requires CSS selectors to meaningfully steal sensitive user data like so:
which is possible within inline <style> tags, but not within inline style attributes. But I don't know the whole picture of what could be possible there.
Motivation
with #17 and #20, strict inline styles are supported in principle. It is heavily dependent on the CSS-in-JS framework though, the only one not messing stuff up so far after prerendering is Stitches. emotion and styled-components do in various ways where I see no way yet as you would control/account for that. I conjecture, that in general, the more runtime-heavy the framework is, the less likely it will work.
Remark: Stitches is the tiniest, most minimalist, elegant, fastest, zero-dependency, zero Babel plugins CSS-in-JS package out there and I absolutely love it. I just ported the styles of a website from emotion+twin.macro to stitches+twin.macro and it was fairly easy. Plus some very ugly FOUCs I had with emotion and couldn't get rid of, magically vanished. Better UX + rock-solid CSP to protect against CSS Keylogging. Win Win 😁.
However, there are still inline-style situations this doesn't cover. Sometimes external stuff you can't control adds styles via the HTML style attribute to elements (e.g. the default NextJS 404 page/error components, the optimized responsive image component of DatoCMS, ...)
Possible Solution
Since the inline styles in question are all scattered throughout
<body>
, the_document
drop-ins had to be extended to consider main content that holds the pages prerendered output (go overinitialProps.html)
. Then we could recurse through them and pick up hashes or apply a nonce. However, inline style attributes can't be nonced, and hashed inline styles attributes are only respectedstyle-src 'unsafe-hashes'
.Restriction
Like with styles and scripts handled in
<Head>
, we can only ever account for what happens during prerendering on the server, anything libs do with styles after hydration is out of control (it is really unfortunate, that the transitive trust propagation of'strict-dynamic'
doesn't apply tostyle-src
- that would've completely solved that problem ).Possible workaround
You can set
style-src-attr 'unsafe-inline'
. This will allow unhashed/unnonced inline attribute styles but not inline<style>
tags. Maybe that isn't even much of a problem, after all. An actual exploit I know (https://github.com/maxchehab/CSS-Keylogging) wouldn't be possible, since it requires CSS selectors to meaningfully steal sensitive user data like so:which is possible within inline
<style>
tags, but not within inline style attributes. But I don't know the whole picture of what could be possible there.References