diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d63cb8d --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules +*.log +.next +.history +package-lock.json +yarn.lock +notes.md +.DS_Store +src +tsconfig.json +.babelrc diff --git a/README.md b/README.md new file mode 100644 index 0000000..a2d7edd --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +![Alt](/public/guy-dumais-logo.svg "Guy Dumais") + +# Next.js Strict Content Security Policy +Hash-based Strict Content Security Policy generator for Next.js to protect a single-page app (SPA) against XSS and CSP bypass. + +## Why +Based on a study from Google: +1. 95% of real-world CSP deployments are bypassed. +2. 99.34% of hosts with CSP use policies that offer no benefit against XSS. + +By using this package in your Next.js website you'll protect your single-page app (SPA) built with Next.js against XSS and CSP bypass. + +## How to install +With NPM: +``` +npm install next-strict-csp +``` + +With YARN: +``` +yarn add next-strict-csp +``` + +## Basic usage +Integrate the CSP generator in your `_document.tsx` this way: + +**_document.tsx** + +``` +... + +// Next.js libraries +import Document, { Html, Head, Main, NextScript } from 'next/document' + +// Next Strict Content Security Policy +import { NextStrictCSP } from 'next-strict-csp' + +... + +// Enable Head Strict CSP in production mode only +const HeadCSP = process.env.NODE_ENV === 'production' ? NextStrictCSP : Head + +... + +// Document component +class MyDoc extends Document { + + render() { + return ( + + + { process.env.NODE_ENV === 'production' && + + } + + ... + + + + + ... + +
+ + + ... + + + + ) + } + +} + +``` + +## Advanced usage with inline scripts +You can also integrate any additionnal inline scripts and they'll get hashed automatically. Here's an example to add Google Tag Manager and Cloudflare Analytics inline scripts: + +**_document.tsx** + +``` +... + +// Next.js libraries +import Document, { Html, Head, Main, NextScript } from 'next/document' + +// Next Strict Content Security Policy +import { NextStrictCSP } from 'next-strict-csp' + +... + +// Cloudflare Insights Script (Optional) +const cloudflareJs = `var s = document.createElement('script') +s.src = 'https://static.cloudflareinsights.com/beacon.min.js' +s.setAttribute('data-cf-beacon', '{"token": "YOUR CLOUDFLARE WEB ANALYTICS TOKEN STRING"}') +document.body.appendChild(s)` + +// Google Tag Manager Script (Optional) +const GTMJs = `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': +new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], +j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= +'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); +})(window,document,'script','dataLayer','YOUR GOOGLE TAG MANAGER ID STRING');` + +// Next Strict CSP +// Inline scripts to hash (Optional) +NextStrictCSP.inlineJs = [ + cloudflareJs, + GTMJs +] + +... + +// Enable Head Strict CSP in production mode only +const HeadCSP = process.env.NODE_ENV === 'production' ? NextStrictCSP : Head + +... + +// Document component +class MyDoc extends Document { + + render() { + return ( + + + { process.env.NODE_ENV === 'production' && + + } + + ... + + {/* Google Tag Manager */} + { process.env.NODE_ENV === 'production' && + */} + {process.env.NODE_ENV === 'production' && +