Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Custom CSP for Payload in Express server with frontend app

default discord avatar
58bitslast year

Posting here in case anyone else comes across this. We have a custom express server serving both Payload and our frontend app. Payload admin is available via

/admin

The frontend app and Payload have quite different CSP settings. If you're using

https://helmetjs.github.io/

- then you can chain helmet middleware and return different policies depending on the request path. For example...



// CSP policy via helmet
app.use(function (req, res, next) {
  let middleware
  // If we've mounted Payload CMS on /admin - change the CSP to suit.
  if (req.path.startsWith('/admin')) {
    middleware = helmet({
      contentSecurityPolicy: {
        'script-src': [
            "'self'"
          ],
          'img-src': ["'self'", 'data:', 'cdn.yourcdn.com'],
          'media-src': ["'self'", 'data:', 'cdn.yourcdn.com'],
          'default-src': ["'self'"]
      }
    })
  } else {
    middleware = helmet({
      crossOriginEmbedderPolicy: false,
      contentSecurityPolicy: {
        // NOTE: Remove reportOnly when you're ready to enforce this CSP
        // reportOnly: true,
        directives: {
          'connect-src': [
            ENVIRONMENT === 'development' ? 'ws:' : null,
            "'self'",
          ].filter(Boolean),
          'script-src': [
            "'strict-dynamic'",
            "'self'", // Ignored by CSP 3 compliant browsers when strict-dynamic - here for backwards compat.
            "'unsafe-inline'", // Ignored by CSP 3 compliant browsers when strict-dynamic - here for backwards compat.
            'https:', // Ignored by CSP 3 compliant browsers when strict-dynamic - here for backwards compat.
            'http:', // Ignored by CSP 3 compliant browsers when strict-dynamic - here for backwards compat.
            (_, res) => `'nonce-${res.locals.cspNonce}'`
          ],
          'script-src-attr': [
            (_, res) => `'nonce-${res.locals.cspNonce}'`
          ],
          'font-src': ["'self'"],
          'frame-src': ["'self'"],
          'img-src': ["'self'", 'data:', 'cdn.yourcdn.com'],
          'media-src': ["'self'", 'data:', 'cdn.yourcdn.com'],
          'default-src': ["'self'"],
          'upgrade-insecure-requests': null
        }
      }
    })
  }

  middleware(req, res, next)
})

Hope this helps ;-)

    Star on GitHub

    Star

    Chat on Discord

    Discord

    online

    Can't find what you're looking for?

    Get dedicated engineering support directly from the Payload team.