Search code examples
node.jsexpresscors

ExpressJS CORS blocking image request


I have an Express JS server running on domain A. It hosts static files including some images and JavaScript modules. I have the CORS middleware installed on the server to ensure requests are allowed only from domains that are approved. The CORS options check the origin of the request agains a list of allowed domains. When a page on one of those allowed domains uses and img tag to with its src set to the path of the image on the Express server, the Express server returns a 500 error. This appears to be because the browser does not set an origin header with the request, just a referer.

Server file structure:

root
  - images
  - modules
  app.js
  package.json
  package-lock.json

The Express server code:

const express = require('express');
const cors = require('cors');
const app = express();

const allowedOrigins = [/\.domainb\.com$/, /\.domainc\.com$/];

const testOrigin = function (origin) {
  let allowed = false;

  for (var i = 0; i < allowedOrigins.length; i++) {
    if (allowedOrigins[i].test(origin)) {
      allowed = true;
    }
  }

  return allowed;
};

const corsOptions = {
  credentials: true,
  origin: function (origin, callback) {
    if (testOrigin(origin)) {
      console.log('corsOptions has true test result');
      callback(null, true);
    } else {
      callback(new Error(origin + ' is not on list of allowed origins'));
    }
  },
};

// cors pre-flights
app.options('*', cors());

app.use(cors(corsOptions));
app.use(express.static('modules'));
app.use(express.static('images'));

module.exports = app;

app.listen(8000, () => {
  console.log(`Express server listening on port 8000`);
});

Not sure if the options here are to attempt to test the referer header within CORS options, to bypass CORS for the static images or something else.


Solution

  • One possible solution is to add the crossorigin attribute to the img tag in your HTML files (assuming you can), and the browser will include an Origin header with the request and check for CORS permissions.

    Once you do that, any request without the Origin header can be safely rejected as it does not come from your client pages.

    <img crossorigin="anonymous | use-credentials" src="http..." />