Protect your Next.js app with security headers

Oslaw Dev
5 min readDec 11, 2020

--

You write highly scalable, easy readable and reusable code. Your test coverage is 99,9%. Your UI is robust and performance is amazing. You document components like a boss and still have time for a coffee. But wait, what about security?

What about it?

Usually security measures is something that happens on the server side while the front end, being exposed to the client, has no way of hiding things and normally you just need to avoid using dangerouslySetInnerHTML and eval() in your code, don’t forget to set up appropriate response headers in your ajax requests and you’ll be just fine.

But when you are working with Next.js (which as we know is built on top of Node.js)you have more tools in your belt to protect your application programmatically without resorting to server-side configurations giving a little break to DevOps in your company. One of these tools is possibility to set up security headers.

So, let’s take a look at the basic security test I ran with Mozilla observation https://observatory.mozilla.org/ on a Next.js app that got to my hands.

Doesn’t look good, does it?

It seems we have a bunch of holes for potential hacker attacks. To fix this, let’s go through the basic steps and eliminate each one of these issues one by one.

Content Security Policy

Content Security Policy (CSP) is an HTTP header that allows site operators fine-grained control over where resources on their site can be loaded from. The use of this header is the best method to prevent cross-site scripting (XSS) vulnerabilities.

Read more about it: https://infosec.mozilla.org/guidelines/web_security#content-security-policy

To fix this issue we will use the nice NPM package next-secure-headers

  1. First step is installing this package in your application npm i next-secure-headers
  2. You are amazing! Now it is time to configure the webpack. In Next.js you can’t directly configure webpack, instead you need to create (if you already didn’t) next.config.js in the root directory of the app.
  3. Then import createSecureHeaders plugin in webpack configuration as in the snipped below

Where “https://trustworhydomain.com” is a domain you trust, for example your api or CDN library required for the application. The rest of the parameters are set to self, which means you allow to load images, styles and scripts only from your domain. In my case I have some inline styles as well, so I had also to set up style src with ‘unsafe-inline’ parameter. Beware though, setting default-src and script-src to ‘self’ will prevent from loading inline scripts!

Subresource integrity

Subresource integrity is a recent W3C standard that protects against attackers modifying the contents of JavaScript libraries hosted on content delivery networks (CDNs) in order to create vulnerabilities in all websites that make use of that hosted library.

From: https://infosec.mozilla.org/guidelines/web_security#subresource-integrity

To fix this we will use webpack-subresource-integrity

After installation lets add these lines in next.config.js

Amazing, lets move forward! And kill the rest of the vulnerabilities in one shot!

What is there remains?

HTTP Strict Transport Security (HSTS)

HTTP Strict Transport Security (HSTS) is an HTTP header that notifies user agents to only connect to a given site over HTTPS, even if the scheme chosen was HTTP. Browsers that have had HSTS set for a given site will transparently upgrade all requests to HTTPS. HSTS also tells the browser to treat TLS and certificate-related errors more strictly by disabling the ability for users to bypass the error page.

From: https://infosec.mozilla.org/guidelines/web_security#http-strict-transport-security

X-Content-Type-Options

X-Content-Type-Options is a header supported by Internet Explorer, Chrome and Firefox 50+ that tells it not to load scripts and stylesheets unless the server indicates the correct MIME type. Without this header, these browsers can incorrectly detect files as scripts and stylesheets, leading to XSS attacks. As such, all sites must set the X-Content-Type-Options header and the appropriate MIME types for files that they serve.

From: https://infosec.mozilla.org/guidelines/web_security#x-content-type-options

X-Frame-Options

X-Frame-Options is an HTTP header that allows sites control over how your site may be framed within an iframe. Click jacking is a practical attack that allows malicious sites to trick users into clicking links on your site even though they may appear to not be on your site at all. As such, the use of the X-Frame-Options header is mandatory for all new websites, and all existing websites are expected to add support for X-Frame-Options as soon as possible.

From: https://infosec.mozilla.org/guidelines/web_security#x-frame-options

X-XSS-Protection

X-XSS-Protection is a feature of Internet Explorer and Chrome that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although these protections are largely unnecessary in modern browsers when sites implement a strong Content Security Policy that disables the use of inline JavaScript ('unsafe-inline'), they can still provide protections for users of older web browsers that don’t yet support CSP.

From: https://infosec.mozilla.org/guidelines/web_security#x-xss-protection

After all manipulations our config will look like this:

If you are not sure about parameters, the official next-secure-headers documentation has very informative descriptions https://www.npmjs.com/package/next-secure-headers

Now lets run our tests again

Yeah, that’s more like it!

Still we have some space to improve and it doesn’t mean that our app became completely hacker-proof, but we made important basic steps to secure our creation.

Liked the story? Consider support: https://ko-fi.com/oslavtichie

--

--