Shield Your Next.js App With a Content Security Policy

Rate this content
Bookmark
Github
In this talk, the importance of implementing a Content Security Policy (CSP) in Next.js applications is discussed. A CSP is a security layer that restricts browser functionality to protect against cross-site scripting and data injection attacks. You can implement a CSP using meta tags or headers, and in Next.js, directives can be added in the next config file. Tools like csp-evaluator.withgoogle.com and observatory.mozilla.org can help validate your CSP. The concept of a nonce is explained, which allows inline scripts to execute securely. Implementing a report-only CSP initially is recommended to identify and resolve issues before enforcement. You can find a sample Next.js app with CSP on GitHub. The talk also covers how server components retrieve the nonce from the header and how middleware sets the CSP request header. Strategies for dynamically applying directives based on the environment are shared. The video provides a comprehensive guide for developers looking to enhance their Next.js app security with a CSP.

From Author:

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.

This talk has been presented at React Advanced Conference 2023, check out the latest edition of this React Conference.

Watch video on a separate page

FAQ

Lucas Esteveau is a lead UI engineer contractor from Avenue Code at Apple and the host of a Brazilian Portuguese podcast about careers in tech.

A Content Security Policy (CSP) is a security layer that helps shield web applications from attacks such as cross-site scripting and data injection by restricting browser functionality based on defined policy directives.

A CSP is important because browsers are not 100% safe from attacks. Even with built-in security features and sanitized code, applications can still be vulnerable to cross-site scripting and data injection attacks. A CSP adds an extra layer of security to help prevent these issues.

In a Next.js application, a CSP can be implemented by adding a list of directives in the header inside the next config file. The directives will specify which sources of content are allowed.

Policy directives in a CSP are rules that define which sources of content are allowed by the browser. For example, you can specify that content should only come from your domain and allow exceptions for fonts from Google Web Fonts.

A CSP can be implemented in two ways: by adding a meta tag in the HTML head or by creating a header for it. The preferred and more secure method is to create a header.

You can validate your CSP using resources like csp-evaluator.withgoogle.com or observatory.mozilla.org to ensure that everything is set up correctly and follows best practices.

A nonce is a random string or hash created for one-time use that allows inline scripts to execute without losing the security of your CSP. It ensures that only scripts with the matching nonce attribute will be executed.

You can test your CSP by first implementing a report-only CSP. This will allow you to review the results and identify any issues before fully enforcing the policy.

You can find a sample Next.js app with a CSP implemented on Lucas Esteveau's GitHub.

Lucas Estevão
Lucas Estevão
6 min
23 Oct, 2023

Comments

Sign in or register to post your comment.

Video Transcription

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

Building Better Websites with Remix
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a web framework built on React Router that focuses on web fundamentals, accessibility, performance, and flexibility. It delivers real HTML and SEO benefits, and allows for automatic updating of meta tags and styles. It provides features like login functionality, session management, and error handling. Remix is a server-rendered framework that can enhance sites with JavaScript but doesn't require it for basic functionality. It aims to create quality HTML-driven documents and is flexible for use with different web technologies and stacks.
Speeding Up Your React App With Less JavaScript
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Top Content
Watch video: Speeding Up Your React App With Less JavaScript
Mishko, the creator of Angular and AngularJS, discusses the challenges of website performance and JavaScript hydration. He explains the differences between client-side and server-side rendering and introduces Quik as a solution for efficient component hydration. Mishko demonstrates examples of state management and intercommunication using Quik. He highlights the performance benefits of using Quik with React and emphasizes the importance of reducing JavaScript size for better performance. Finally, he mentions the use of QUIC in both MPA and SPA applications for improved startup performance.
Full Stack Documentation
JSNation 2022JSNation 2022
28 min
Full Stack Documentation
Top Content
The Talk discusses the shift to full-stack frameworks and the challenges of full-stack documentation. It highlights the power of interactive tutorials and the importance of user testing in software development. The Talk also introduces learn.svelte.dev, a platform for learning full-stack tools, and discusses the roadmap for SvelteKit and its documentation.
Routing in React 18 and Beyond
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Routing in React 18 brings a native app-like user experience and allows applications to transition between different environments. React Router and Next.js have different approaches to routing, with React Router using component-based routing and Next.js using file system-based routing. React server components provide the primitives to address the disadvantages of multipage applications while maintaining the same user experience. Improving navigation and routing in React involves including loading UI, pre-rendering parts of the screen, and using server components for more performant experiences. Next.js and Remix are moving towards a converging solution by combining component-based routing with file system routing.
SolidJS: Why All the Suspense?
JSNation 2023JSNation 2023
28 min
SolidJS: Why All the Suspense?
Top Content
Suspense is a mechanism for orchestrating asynchronous state changes in JavaScript frameworks. It ensures async consistency in UIs and helps avoid trust erosion and inconsistencies. Suspense boundaries are used to hoist data fetching and create consistency zones based on the user interface. They can handle loading states of multiple resources and control state loading in applications. Suspense can be used for transitions, providing a smoother user experience and allowing prioritization of important content.
From GraphQL Zero to GraphQL Hero with RedwoodJS
GraphQL Galaxy 2021GraphQL Galaxy 2021
32 min
From GraphQL Zero to GraphQL Hero with RedwoodJS
Top Content
Tom Pressenwurter introduces Redwood.js, a full stack app framework for building GraphQL APIs easily and maintainably. He demonstrates a Redwood.js application with a React-based front end and a Node.js API. Redwood.js offers a simplified folder structure and schema for organizing the application. It provides easy data manipulation and CRUD operations through GraphQL functions. Redwood.js allows for easy implementation of new queries and directives, including authentication and limiting access to data. It is a stable and production-ready framework that integrates well with other front-end technologies.

Workshops on related topic

Building WebApps That Light Up the Internet with QwikCity
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Miško Hevery
Miško Hevery
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.
Back to the Roots With Remix
React Summit 2023React Summit 2023
106 min
Back to the Roots With Remix
Featured Workshop
Alex Korzhikov
Pavlik Kiselev
2 authors
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)
Build a Headless WordPress App with Next.js and WPGraphQL
React Summit 2022React Summit 2022
173 min
Build a Headless WordPress App with Next.js and WPGraphQL
Top Content
WorkshopFree
Kellen Mace
Kellen Mace
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.
Next.js 13: Data Fetching Strategies
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
Alice De Mauro
Alice De Mauro
- 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
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
React Summit 2023React Summit 2023
139 min
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
Top Content
WorkshopFree
Matteo Frana
Matteo Frana
- 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
From Todo App to B2B SaaS with Next.js and Clerk
React Summit US 2023React Summit US 2023
153 min
From Todo App to B2B SaaS with Next.js and Clerk
WorkshopFree
Dev Agrawal
Dev Agrawal
If you’re like me, you probably have a million side-project ideas, some that could even make you money as a micro SaaS, or could turn out to be the next billion dollar startup. But how do you know which ones? How do you go from an idea into a functioning product that can be put into the hands of paying customers without quitting your job and sinking all of your time and investment into it? How can your solo side-projects compete with applications built by enormous teams and large enterprise companies?
Building rich SaaS products comes with technical challenges like infrastructure, scaling, availability, security, and complicated subsystems like auth and payments. This is why it’s often the already established tech giants who can reasonably build and operate products like that. However, a new generation of devtools are enabling us developers to easily build complete solutions that take advantage of the best cloud infrastructure available, and offer an experience that allows you to rapidly iterate on your ideas for a low cost of $0. They take all the technical challenges of building and operating software products away from you so that you only have to spend your time building the features that your users want, giving you a reasonable chance to compete against the market by staying incredibly agile and responsive to the needs of users.
In this 3 hour workshop you will start with a simple task management application built with React and Next.js and turn it into a scalable and fully functioning SaaS product by integrating a scalable database (PlanetScale), multi-tenant authentication (Clerk), and subscription based payments (Stripe). You will also learn how the principles of agile software development and domain driven design can help you build products quickly and cost-efficiently, and compete with existing solutions.