Shield Your Next.js App With a Content Security Policy

Rate this content
Bookmark
Github

Learn why you should care about Content Security Policy (CSP) and how to implement it in a Next.JS application to level up your security layer. Understand CSP basics, directives, and their role in thwarting web attacks. Moving on to Next.js, the session will delve into implementation details, covering the "nounce" hashes for inline scripts using middlewares and common strategy pitfalls. By the end of the session, participants will be equipped with the knowledge and skills to implement and evaluate a robust CSP policy in Next.js, leveraging its latest features from version 13, effectively safeguarding their web applications against online attacks.

6 min
23 Oct, 2023

AI Generated Video Summary

Lucas Esteveau discusses the importance of Content Security Policy (CSP) as an additional layer of security for browsers. He explains how to validate and implement CSP using tools like csp-evaluator.withgoogle.com and observatory.mozilla.org. He also highlights the use of server components and middleware in the Hudafor project to set and enforce CSP directives. Lucas advises starting with a report-only CSP, reviewing the results, and gradually enforcing the policy. He emphasizes the importance of reviewing policy violation reports and iterating the process when making changes.

1. Introduction to Content Security Policy

Short description:

I'm Lucas Esteveau, a lead UI engineer contractor from Avenue Code at Apple. Let's talk about why you should care about a Content Security Policy. Browsers have security features, but they can't prevent all attacks. A CSP is a layer of security that restricts browser functionality. You can implement it using meta tags or headers. In Next.js, you can add directives in your next config file.

Hi, everyone. Thanks for having me at the React Advanced Conference 2023. I'm Lucas Esteveau. I'm a lead UI engineer contractor from Avenue Code at Apple since I moved to California about four years ago. I also host a Brazilian Portuguese podcast about career in tech. So if you're curious and are a Portuguese speaker, check it out on the major streaming platforms.

I'm really excited to talk to you about how should your Next.js app with a Content Security Policy today and I want to start answering why should I care about a Content Security Policy? Well, it turns out your browser is not 100% safe. Whether it's React or Next.js or any library or framework that you might be using for your web application. Although browsers do have security built-in features like single origin policy and course and libraries and frameworks like React and Next.js do a pretty decent job sanitizing the code and providing web features to close security gaps, we can't take it for granted. If a code like this is injected in your website, your browser or React default features can't prevent this from being executed. Meaning, your app could be exposed to cross-type scripting attacks, and precious data could be leaked.

That's when a CSP comes handy. A content security policy. It's a layer for security that helps to shield applications from attacks like cross-type scripting attacks, or data injection attacks, and it does it by restricting browser functionality. A content security policy is composed by a list of policy directives. The browser will be limited to allow only what you define in your policy. So here is an example of how a content security policy is composed. Here another example, where the policy directives, where I'm defining that the default sources content, let me go back to this one. Here are examples of policy directives where I'm defining that the default sources of content should come from my domain. And I'm adding an exception for fonts, because I want to allow Google Web Fonts to be downloaded.

There are two ways to implement a content security policy in your application. The first one is by adding a meta tag in the HTML head, but this one is not preferred. The other way, and the best way to go, is to create a header for it. So here we are adding a CSP key and the value that will hold our directives. In this case, as I said before, I'm saying that the default source of my content, it's gonna come from my domain, and adding an exception for fonts that can also come from Google. When it comes to Next.js, this is how a CSP looks like. You can simply add a list of directives in your header inside your next config file. You may define what kind of requests the CSP will be applied to using the source attribute. In this case, I'm saying that my content security policy will be applied for every single request. I'm not filtering, although you could do it, filtering your API for example.

2. CSP Validation and Implementation

Short description:

To validate your CSP, you can use csp-evaluator.withgoogle.com or observatory.mozilla.org. Announced allows executing inline scripts securely. Server components retrieve the announce from the header. A middleware in the Hudafor project sets the announce on the request header. The middleware defines directives and sets the CSP request header. Apply directives dynamically based on the environment. Start with report-only CSP, review the results, and enforce later. The browser sends a report with a POST request to the defined endpoint. Review the report for policy violations. Repeat the process when making changes. Find the sample Next.js app with CSP on my GitHub.

What about validation? It's pretty simple. You have pretty much two resources that you can use to validate your CSP. You can check it out going to csp-evaluator.withgoogle.com or to observatory.mozilla.org. Make sure that everything looks good, you're following the best practice, and move the code to your own app.

There will be cases when you need inline scripts. For those scenarios, announced will allow your scripts to execute without losing the security of your CSP. Announced is pretty much a random string, a hash created for one-time use. Let's see how announced can be used in a server component. On a strict CSP policy set, modern browsers will only execute scripts whose announced attribute matches the value set in the policy header. Scripts dynamically added to the page by scripts with the proper announce will also be executed.

This is how a server component looks like, as I said, getting the announce from the header. To expose the announce, we need to create a middleware in the Hudafor project and set the announce on the request header. Here we are doing this with the help of crypto. To use the announce on our policy, we can define the directives and set the CSP request header inside our middleware. We can even apply directives dynamically depending on the environment we are. Here I'm checking if I'm not in production and if I'm not, I can lose my CSP security since I'm on developing mode. This is how our middleware looks like. I know it looks a lot, but don't worry about every line of code. The idea here is that you understand the process. You can check my code on my GitHub.

But let's review it. First we create the announce, then we define our CSP and we add both to the request headers. You don't need to apply all the rules at once and risk breaking your app. You can add the report-only CSP first, reveal the results, and enforce it later. This is how a report-only CSP looks like, very similar to the regular one. The browser will send an HTTP POST request to the endpoint we define, with a report that looks like this. You can see the original policy and review what's breaking. And then you can repeat this process when you make changes to your policy. Report-only, reveal, and enforce. Thank you. I hope you found this content useful. You can find the sample Next.js app with a CSP implemented on my GitHub.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Too much JavaScript is getting you down? New frameworks promising no JavaScript look interesting, but you have an existing React application to maintain. What if Qwik React is your answer for faster applications startup and better user experience? Qwik React allows you to easily turn your React application into a collection of islands, which can be SSRed and delayed hydrated, and in some instances, hydration skipped altogether. And all of this in an incremental way without a rewrite.
JSNation 2022JSNation 2022
28 min
Full Stack Documentation
Interactive web-based tutorials have become a staple of front end frameworks, and it's easy to see why — developers love being able to try out new tools without the hassle of installing packages or cloning repos.But in the age of full stack meta-frameworks like Next, Remix and SvelteKit, these tutorials only go so far. In this talk, we'll look at how we on the Svelte team are using cutting edge web technology to rethink how we teach each other the tools of our trade.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
GraphQL Galaxy 2021GraphQL Galaxy 2021
32 min
From GraphQL Zero to GraphQL Hero with RedwoodJS
We all love GraphQL, but it can be daunting to get a server up and running and keep your code organized, maintainable, and testable over the long term. No more! Come watch as I go from an empty directory to a fully fledged GraphQL API in minutes flat. Plus, see how easy it is to use and create directives to clean up your code even more. You're gonna love GraphQL even more once you make things Redwood Easy!
JSNation 2023JSNation 2023
28 min
SolidJS: Why All the Suspense?
Solid caught the eye of the frontend community by re-popularizing reactive programming with its compelling use of Signals to render without re-renders. We've seen them adopted in the past year in everything from Preact to Angular. Signals offer a powerful set of primitives that ensure that your UI is in sync with your state independent of components. A universal language for the frontend user interface.
But what about Async? How do we manage to orchestrate data loading and mutation, server rendering, and streaming? Ryan Carniato, creator of SolidJS, takes a look at a different primitive. One that is often misunderstood but is as powerful in its use. Join him as he shows what all the Suspense is about.

Workshops on related topic

JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Building instant-on web applications at scale have been elusive. Real-world sites need tracking, analytics, and complex user interfaces and interactions. We always start with the best intentions but end up with a less-than-ideal site.
QwikCity is a new meta-framework that allows you to build large-scale applications with constant startup-up performance. We will look at how to build a QwikCity application and what makes it unique. The workshop will show you how to set up a QwikCitp project. How routing works with layout. The demo application will fetch data and present it to the user in an editable form. And finally, how one can use authentication. All of the basic parts for any large-scale applications.
Along the way, we will also look at what makes Qwik unique, and how resumability enables constant startup performance no matter the application complexity.
React Summit 2023React Summit 2023
106 min
Back to the Roots With Remix
Featured Workshop
The modern web would be different without rich client-side applications supported by powerful frameworks: React, Angular, Vue, Lit, and many others. These frameworks rely on client-side JavaScript, which is their core. However, there are other approaches to rendering. One of them (quite old, by the way) is server-side rendering entirely without JavaScript. Let's find out if this is a good idea and how Remix can help us with it?
Prerequisites- Good understanding of JavaScript or TypeScript- It would help to have experience with React, Redux, Node.js and writing FrontEnd and BackEnd applications- Preinstall Node.js, npm- We prefer to use VSCode, but also cloud IDEs such as codesandbox (other IDEs are also ok)
React Summit 2022React Summit 2022
173 min
Build a Headless WordPress App with Next.js and WPGraphQL
WorkshopFree
In this workshop, you’ll learn how to build a Next.js app that uses Apollo Client to fetch data from a headless WordPress backend and use it to render the pages of your app. You’ll learn when you should consider a headless WordPress architecture, how to turn a WordPress backend into a GraphQL server, how to compose queries using the GraphiQL IDE, how to colocate GraphQL fragments with your components, and more.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
WorkshopFree
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
React Summit 2023React Summit 2023
56 min
0 to Auth in an hour with ReactJS
WorkshopFree
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool. There are multiple alternatives that are much better than passwords to identify and authenticate your users - including SSO, SAML, OAuth, Magic Links, One-Time Passwords, and Authenticator Apps.
While addressing security aspects and avoiding common pitfalls, we will enhance a full-stack JS application (Node.js backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session securely for subsequent client requests, validating / refreshing sessions- Basic Authorization - extracting and validating claims from the session token JWT and handling authorization in backend flows
At the end of the workshop, we will also touch other approaches of authentication implementation with Descope - using frontend or backend SDKs.
React Summit 2023React Summit 2023
139 min
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
WorkshopFree
- React Bricks: why we built it, what it is and how it works- Create a free account- Create a new project with Next.js and Tailwind- Explore the directory structure- Anatomy of a Brick- Create a new Brick (Text-Image)- Add a title and description with RichText visual editing- Add an Image with visual editing- Add Sidebar controls to edit props (padding and image side)- Nesting Bricks using the Repeater component- Create an Image gallery brick- Publish on Netlify or Vercel- Page Types and Custom fields- Access Page meta values- Internationalization- How to reuse content across pages: Stories and Embeds- How to create an E-commerce with Products’ data from an external database and landing pages created visually in React Bricks- Advanced enterprise features: flexible permissions, locked structure, custom visual components