How to fix “Refused to connect to xxx because it violates the following Content Security Policy directive” on Heroku

I’ve deployed a MERN stack app to Heroku: Mongo DB, Express.js, React.js, Node.js.

The app uses Google Fonts and Stripe Checkout.

I’ve built the React app via Create React App.

My last deploy went wonkers. The app didn’t load any JavaScript because of Content-Security-Policy failures.

In this post I’ll show you how to fix those errors and how to successfully re-deploy your MERN app to Heroku.

What is Content-Security-Policy?

Content-Security-Policy is the name of a HTTP response header that modern browsers use to enhance the security of the document (or web page). The Content-Security-Policy header allows you to restrict how resources such as JavaScript, CSS, or pretty much anything that the browser loads. 1

How to Fix React/Create React App

In production, React will embed the React app as an inline script into index.html.

To fix that, add an environment variable INLINE_RUNTIME_CHUNK and set it to false.

You’ll need to add the variable to your Heroku configuration, see Configuration and Config Vars.

How to Fix CSP

You’ll need helmet for your Express.js/Node.js server:

const express = require('express')
const helmet = require('helmet')
const app = express()

app.use(
  // [
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      connectSrc: ["'self'", 'https://checkout.stripe.com'],
      frameSrc: ["'self'", 'https://checkout.stripe.com'],
      childSrc: ["'self'", 'https://checkout.stripe.com'],
      scriptSrc: ["'self'", 'https://checkout.stripe.com'],
      styleSrc: [
        "'self'",
        'https://fonts.googleapis.com',
        'https://checkout.stripe.com',
      ],
      fontSrc: ["'self'", 'https://fonts.gstatic.com'],
      imgSrc: ["'self'", 'https://*.stripe.com', 'https://res.cloudinary.com'],
      baseUri: ["'self'"],
    },
  })
  // ]
)

This works for Google Fonts, images from Cloudinary and Stripe Checkout. If you use Stripe.js, replace https://checkout.stripe.com with the values found on the official documentation page.

When you allow self, you’re telling the browser that you allow loading resources from the same origin. That works because Heroku deploys your resources at the Heroku url. For example, your React app is at https://<your-heroku-app>.herokuapp.com/static/js/main.<some-random-string>.chunk.js.

I found the script on GitHub and adjusted it to my needs.

Recap

You’ve now learned how to work with the Content-Security-Policy for a MERN stack app. You have to add a few configuration options in your server-side code. That’s it!

Further Reading


  1. CSP ↩︎