helmet: After update issue ERR_BLOCKED_BY_RESPONSE

I am getting this error after update net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep 200

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 5
  • Comments: 27 (13 by maintainers)

Most upvoted comments

tl;dr: disable the Cross-Origin-Embedder-Policy header, enabled by default in Helmet v5.

app.use(
  helmet({
    crossOriginEmbedderPolicy: false,
    // ...
  })
);

Helmet v5 sets the the Cross-Origin-Embedder-Policy HTTP response header to require-corp. (This was possible in Helmet v4, but it was off by default, so most people didn’t use it.)

Setting this header means that loading cross-origin resources (like an image from another resource) is trickier. For example, loading a cross-origin like this…

<img alt="My picture" src="https://example.com/image.png">

…won’t work unless example.com explicitly allows it, by setting some response headers of its own. Your browser will try to load example.com/image.png, and if it’s not explicitly allowed, your browser will drop the response.

To fix this, you can prevent Helmet from setting the Cross-Origin-Embedder-Policy header, like this:

app.use(
  helmet({
    crossOriginEmbedderPolicy: false,
    // ...
  })
);

I made a small sample app you can use to play around with this. In my testing, it doesn’t seem to work in HTTP but it does over HTTPS, which might explain why things only break in production.

I think this solves the problem so I’m going to close this issue. Let me know if that’s wrong and I’ll reopen!

@K-404 Not quite. Your options are:

  1. Use the top-level Helmet and disable the crossOriginEmbedderPolicy middleware.

    app.use(
      helmet({
        crossOriginEmbedderPolicy: false,
        // ...
      })
    );
    
  2. I do not recommend this, but you can use the top-level Helmet and then manually remove the Cross-Origin-Embedder-Policy header later.

    app.use(helmet());
    
    app.use((req, res, next) => {
      res.removeHeader("Cross-Origin-Embedder-Policy");
      next();
    });
    

    This should work, but it couples two middlewares. Why not just skip it at the top level?

  3. I do not recommend this, but you can break Helmet into its smaller middlewares and skip helmet.crossOriginEmbedderPolicy.

     app.use(helmet.contentSecurityPolicy());
    -app.use(helmet.crossOriginEmbedderPolicy());
     app.use(helmet.crossOriginOpenerPolicy());
     app.use(helmet.crossOriginResourcePolicy());
     app.use(helmet.dnsPrefetchControl());
     app.use(helmet.expectCt());
     app.use(helmet.frameguard());
     app.use(helmet.hidePoweredBy());
     app.use(helmet.hsts());
     app.use(helmet.ieNoOpen());
     app.use(helmet.noSniff());
     app.use(helmet.originAgentCluster());
     app.use(helmet.permittedCrossDomainPolicies());
     app.use(helmet.referrerPolicy());
     app.use(helmet.xssFilter());
    

    This should work, but it will make Helmet harder to upgrade in the future if middlewares are added or removed.

Hope this helps!

@amitagrawal11 Good idea. I’ll consider creating a separate resource for this.

@manuelpoelzl Thanks for this. I’ll take a look later today.

Hi! After I am also affected by the error and read along here, I quickly created an app on codesandbox, which shows the problem https://codesandbox.io/s/elegant-sinoussi-v9o06?file=/app.js

I am trying to generate an avatar using https://eu.ui-avatars.com/api/?name=John+Doe , and this is exactly where this error occurs, as @krishnaTORQUE already describes, it also occurs here with the subdomain.

Attached is also a screenshot showing the error

Screenshot_1

The is showing in Devtools net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep 200

Helmet Config

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'", 'google.com', 'youtube.com'],
        styleSrc: ["'self'", 'google.com', 'youtube.com', "'unsafe-inline'"],
        scriptSrc: ["'self'", 'google.com', 'youtube.com', "'unsafe-inline'"],
        imgSrc: ["'self'", 'google.com', 'youtube.com', 'data:', 'blob:'],
        connectSrc: ["'self'", 'google.com', 'youtube.com', 'ws:', 'wss:'],
        frameSrc: ["'self'", 'google.com', 'youtube.com'],
        frameAncestors: ["'self'", 'google.com', 'youtube.com'],
        mediaSrc: ["'self'", 'google.com', 'youtube.com', 'data:', 'blob:'],
      },
    },
    frameguard: { action: 'SAMEORIGIN' },
  })
);

This same code works in v4.x but not in v5.x