helmetjs / helmet

Help secure Express apps with various HTTP headers
https://helmetjs.github.io/
MIT License
10.21k stars 367 forks source link

TypeError: directiveValue is not iterable #374

Closed danicunhac closed 2 years ago

danicunhac commented 2 years ago

Hi, I'm using version 5.1.0 and it's throwing me the following error:

/node_modules/helmet/dist/cjs/index.js:64
        for (const element of directiveValue) {
                              ^

TypeError: directiveValue is not iterable
    at normalizeDirectives

I've just installed helmet the way it says in the docs. I'm using node v12.22.3 and no Typescript

EvanHahn commented 2 years ago

Could you post a code snippet of how you're using Helmet?

danicunhac commented 2 years ago
// headers.js
const getCorsHelmetDirectives = () => {
  const self = `'self'`
  const unsafeInline = `'unsafe-inline'`
  const scripts = [
    self,
    `https://localhost`,
    `https://maxcdn.bootstrapcdn.com`,
    `https://js.stripe.com/`,
    `https://code.jquery.com/`,
    `https://cloudflare.com`,
    `https://bootstrapcdn.com`,
    `https://cdnjs.cloudflare.com`,
    `https://cdn.jsdelivr.net`,
  ]
  const styles = [
    self,
    `https://localhost`,
    `https://fonts.googleapis.com/`,
    `https://platform.twitter.com/`,
    `https://js.stripe.com/`,
    `https://maxcdn.bootstrapcdn.com`,
    `https://cdn.jsdelivr.net`,
  ]
  const fonts = [
    self,
    `https://localhost`,
    `https://fonts.gstatic.com/`,
  ]

  const frames = [
    self,
    `https://localhost`,
    `https://www.youtube.com/`,
    `https://speakerdeck.com/`,
    `https://player.vimeo.com/`,
    `https://syndication.twitter.com/`,
    `https://codepen.io/`,
    `https://js.stripe.com`,
    `https://cdn.jsdelivr.net`,
  ]

  const images = [`https:`, `data:`]

  const connect = [
    self,
    `https://api.github.com/`,
    `https://maps.googleapis.com/`,
    `https://js.stripe.com`,
  ]

  return {
    defaultSrc: [self],
    workerSrc: [`all`],
    scriptSrc: [self, getNonce, ...scripts],
    styleSrc: [self, unsafeInline, ...styles],
    fontSrc: [self, ...fonts],
    frameSrc: [self, ...frames],
    connectSrc: [self, ...connect],
    imgSrc: [self, ...images],
    objectSrc: [self],
    upgradeInsecureRequests: true,
    reportUri: `/api/csp/report`,
  }
}
// headers.js
const setContentSecurityPolicy = helmet.contentSecurityPolicy({
  directives: getCorsHelmetDirectives(),
// index.js
app.use(setContentSecurityPolicy)
danicunhac commented 2 years ago

And I'm also importing it like

const { default: helmet } = require('helmet')
EvanHahn commented 2 years ago

I'm away from my computer but upgradeInsecureRequests: true needs to be upgradeInsecureRequests: [], I believe. The report URI might also need to be in an array.

Let me know if this helps.

danicunhac commented 2 years ago

It did solve the problem, but now I'm getting POST http://localhost:3032/api/csp/report net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 204 and also [Report Only] Refused to frame 'http://localhost:3032/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self'".

EvanHahn commented 2 years ago

Both look like issues that are specific to your Content Security Policy.

The first looks like an issue where it's trying to send a CSP violation report (to your reportUri) but it's failing because it's not on the same origin.

The second looks like an issue where it won't put something in an iframe, because the iframe's frame-ancestors directive prohibits it.

danicunhac commented 2 years ago

I'm away from my computer but upgradeInsecureRequests: true needs to be upgradeInsecureRequests: [], I believe. The report URI might also need to be in an array.

Let me know if this helps.

This solution solved the original, the other two are separate ones. I'll close it as it's resolved. Thanks for the help @EvanHahn!

EvanHahn commented 2 years ago

Great! Feel free to open a new issue if you encounter other problems.