CSPs and Next.js


The choice between using nonces and hashes

I wasted quite a few hours today trying to get strict CSPs working correctly with Next.js.

My verdict: just don’t. It can work, but with SSG it doesn’t work very well (for now, at least).
To be clear, some weak CSP is better than none at all, and it does also depend on the libraries you use. But you’re more likely than not going to allow “unsafe-inline” styles and scripts (which are the ones you really shouldn’t allow for good security). So I’d just recommend all the Next.js devs out there to go with the default static example from their docs and call it a day. Not worth the headache unless you really absolutely need it and are willing to pay the price.

A bit of background info

Disclaimer: I’m not an expert in this. This is just what I learned by trying to implement it, researching it and discussing this topic with AI.

Setting strict Content Security Policies (CSPs) can greatly reduce the possible damage of XSS attacks. That’s basically their main purpose. In other words, CSPs are a tool we can use to stop ourselves from accidentally shooting us in the foot.

By not implementing CSPs, you’re not inherently exposing yourself to XSS attacks, it’s just that if your website has such a vulnerability, the possible damage is a lot greater.


Now, a strict CSP (reminder: strict = good) typically avoids unsafe-inline and instead uses nonces or hashes for the inline code you intentionally want to keep:

  • Nonces: the server attaches a random nonce to every request for a website. This is probably the easier way, but it requires SSR. Thus, because every request must contain a new nonce, full-page caching becomes quite difficult. To me, that is a bit unnecessary when the whole page would be static otherwise (remember, in serverless environments we are often billed per request)

  • Hashes: the other possibility is to generate hashes and attach them to their respective inline styles and scripts (basically you create checksums). In theory, this works well with SSG. The downside? Doesn’t really work with Next.js reliably. They do seem to work on something, but from what I understand it’s not really there yet.

An ignored problem

The thing is, CSPs are not exactly new. Pretty much all major browsers support CSPs since 2011. However, I believe that most web devs either don’t know about CSPs or just don’t care (remember, it is possible build secure websites without CSPs).

The result is that pretty much all major js frameworks have no, or often very lackluster CSP implementations. Next.js for example still has hash based CSPs marked experimental. Astros support for CSPs is a bit better from my experience, but their support for both nonce- and hash-based CSPs is also still experimental.

Documentation around CSPs is usually pretty lackluster as well, no matter which js framework you look at.

A solution?

Well, I have to disappoint you here. I don’t really have one. The sad fact is, we are stuck between a rock and a hard place here. The support is just not there yet, and just not using your favorite frameworks is hardly a good solution.

For Next.js devs: You can either choose the nonce route and give up some caching, or implement hash-based allowances which probably will take quite some time (yes, there are some libraries that will help you, but there is no ready made solution like we web developers have often come to expect).

Or you go try out Astro, but that is also not perfect, and after using both Astro and Next.js I think I prefer the latter.

© 2025 Franz Josef Drexler