Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NextJS Content Security Policy (CSP)

I am currently making a Content Security Policy (CSP) for a production application made with Next.js. While I have found trustworthy documentation for implementing a CSP with the framework, there are a couple of concerns that I want to make sure are addressed correctly.

Issue #1: I have read that security policies set in HTTP headers are preferable. However, I cannot find a way to pass a 'nonce' attribute for inline styles in production using this approach. https://nextjs.org/docs/advanced-features/security-headers

Issue #2: I've seen other examples where developers inject their CSP in the custom document("./pages/_document.js"). I am hesitant to use this approach because I hear meta-tag CSPs are easily bypassable. https://github.com/vercel/next.js/tree/canary/examples/with-strict-csp

My Questions:

  1. Is there a way to use a 'nonce' with header configuration in "next.config.js"? If so, how?
  2. Is specifying "unsafe-inline" for styles in production a security issue at all if Next.js automatically sanitizes user input? I should also mention that I sanitize all mongo database queries in my APIs as well.
  3. Is there something about the meta tag approach described in Issue #2 that makes it as secure as the HTTP header approach?
  4. What approach do you recommend I take to make my CSP as strong as possible for my web app?

All the best, -Sam

like image 522
Sam Morgan Avatar asked Dec 19 '25 03:12

Sam Morgan


1 Answers

NextJS has 2 pre-rendering mode: Static Site Generation(SSG) and Server-Side Rendering(SSR). The first one has no way to update nonce='value' in the HTML code, but when using SSR you can pass a 'nonce' attribute for inline styles and scripts using ./pages/_document.tsx.

See an example for CSP header and meta tag CSP example.

Re Questions:

  1. I think using a next.config.js is possible, for example next-safe package adds a nextSafe() function into this file to set a lot of headers:
const nextSafe = require('next-safe')
const isDev = process.env.NODE_ENV !== 'production'
module.exports = {
  async headers () {
    return [
      {
        source: '/:path*',
        headers: nextSafe({ isDev }),
      },
    ]
  },
}

To set 'nonce' into CSP header you can craft your own function in this way. To set 'nonce' attribute into styles you can use _document.tsx renderer.

  1. Specifying 'unsafe-inline' for styles in production is not a security issue. For example https://accounts.google.com page allows inline styles (it even does not have style-src/default-src directives but it carefully controls scripts).

  2. Setting CSP in HTTP headers is preferable but this does not mean that CSP in meta tag is easily bypassable. Just CSP in meta tag has some restrictions and if you do not use features that have been restricted you can safely use meta tag to delivery CSP.

  3. You can strengthen protection indefinitely, spending a lot of time and resources. Just follow the main principle "protection should not be more expensive than the protected object".

like image 174
granty Avatar answered Dec 21 '25 22:12

granty



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!