nibtime / next-safe-middleware

Strict CSP (Content-Security-Policy) for Next.js hybrid apps https://web.dev/strict-csp/
https://next-safe-middleware.vercel.app
MIT License
79 stars 20 forks source link

How to import global CSS files (dynamic tailwind CSS and other static files) from packages? #61

Closed renet closed 2 years ago

renet commented 2 years ago

In our project, we import some global css files (tailwind, which is dynamically generated at build time, and other static CSS files from dependencies as well as a locally stored global.css file) in the _app.tsx. But they seem not to be recognized by the CSP middleware this way. The imports look like this:

import 'tailwindcss/tailwind.css'
import '@emdgroup-liquid/liquid/dist/css/liquid.global.css'
import '../css/global.css'

I tried moving them to the _document.tsx, but as soon as I do this, I get the following error at build time:

CSS cannot be imported within pages/_document.js. Please move global styles to pages/_app.js.

Same goes for some images that are placed in the public folder and referenced in the app using the next/image component (which seems to inline the images).

What would be the proper way to add those files so that they get recognized by the middleware?

Thanks a lot! :)

nibtime commented 2 years ago

Hi @renet

the problem is that processing other sources than inline scripts and styles isn't implemented yet :).

Regarding next/image: I also realized that automatic processing there would be great during setting up the docs project. I added everything to CSP manually and that felt pretty redundant.

I am currently working on it (#40).

When I am done with that issue, there will be a file .next/static/~csp/csp-manifest.json that contains all trustable sources identified during the build process.

Middleware can then read it and is the easiest and most versatile configuration option that uses the manifest. I also intend to split up the package and support others (see https://github.com/nibtime/next-safe-middleware/discussions/60#discussioncomment-3259782).

I was a bit frustrated after the Next 12.2 update, as it introduced a really bad regression to routing together with middleware (even with empty) that also makes the CSP features as a whole unusable when the middleware is the only configuration option. Most code is all the SSR stuff and that can support any version with next/script, so >= 11 and I don't have to keep up with the latest Next versions all the time.

nibtime commented 2 years ago

For clarification: what do you expect the resulting CSP to look like if it was handled automatically?

renet commented 2 years ago

I expect to have a lot of sha256 hashes in the img-src and style-src directives of the CSP. But to be honest, I'm pretty new to the CSP topic, so please don't take my expectations as base for your development. :)

Thanks, this sounds great. Looking forward to the upcoming releases! I already stumbled upon your discussions thread and at least can understand your frustration. I really hope it's not that much of a hassle with future Next.js releases.

nibtime commented 2 years ago

Haha no worries, I won't take it verbatim :). But getting good feedback helps to get ideas for improvements. I am also not an expert on CSPs or something, I made this package for myself and all of the sudden people show up here and use it :) But by doing stuff you learn it.

Regarding images:
I don't think `img-src` supports hashes, as sources. So for inlined images, you have to allow `data:` and `blob:`. For `next-image` it would make sense to pick settings from `next.config.js` automatically, that's the redundant part I was referring to. It would also be possible to add image sources observed in prerendered HTML automatically, but I will make that opt-in, whether I want that depends on the app. For a static MDX site like the docs project e.g. I would turn it on, in an app where users can upload images not, etc.
Regarding stylesheets:
They support the `integrity` attribute. For stylesheets included in `_app.js` as you did, it would be possible to hash and pick them up for CSP. That way you could have `style-src` with sheets and/or CSS-in-JS with crypto sources only, which is basically a guarantee that no visitor will ever experience tampered visuals/look and feel. But that's pretty much already the case with `self`, that isn't problematic just `unsafe-inline` is. So you can just add `self` on top of the injected inline styles and it will be fine.
Regarding the frustration with Next release cycle
I made sure to make the code that handles Next framework scripts during SSR as resilient as possible towards changes. If something discontinues working now, it can only be due to adding/renaming methods in `next/document` and be fixed by extension and won't affect older versions. With that and by decoupling stuff from middleware over several packages, I think maintenance will be fine and stability can be achieved.
nibtime commented 2 years ago

Hi @renet,

I am closing this, I put the possible improvements to my backlog, I will have a look at them sometime after the transition to multiple packages has been done.

What I can really recommend you for stylesheets and images is a semi-automatic approach with a CSP recording tool like Laboratory for Firefox: https://next-safe-middleware.vercel.app/guides/strict-csp-configuration#csp-converter. (Firefox will also be supported for Hash-based Strict CSP in the upcoming version).

I tried this for the docs website and it could have saved me a lot of time. The extension has several recording options for sources, e.g. it can record images or stylesheets by full path. I really like it, it is maybe even preferable to a fully automated approach, since it can accommodate individual requirements better.