From 94a4e08809e015fedda54f6a9aad1c12ebbb9899 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Tue, 19 Apr 2016 13:38:09 +0100 Subject: [PATCH] Add config URLS to CORS whitelist refs #6644 - urls specified in config.js should be considered whitelisted/trusted - this is not quite straightforward because config.js is not ready at the point the middleware is required - tests have been updated to cover these new cases + use rewire to override the internal whitelist cache --- core/server/middleware/cors.js | 34 +++++++++++++++----- core/test/unit/middleware/cors_spec.js | 43 +++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/core/server/middleware/cors.js b/core/server/middleware/cors.js index 6ef4b3f3f6..2ef620e875 100644 --- a/core/server/middleware/cors.js +++ b/core/server/middleware/cors.js @@ -2,9 +2,8 @@ var cors = require('cors'), _ = require('lodash'), url = require('url'), os = require('os'), - whitelist = [ - 'localhost' - ], + config = require('../config'), + whitelist = [], ENABLE_CORS = {origin: true, maxAge: 86400}, DISABLE_CORS = {origin: false}; @@ -14,7 +13,9 @@ var cors = require('cors'), */ function getIPs() { var ifaces = os.networkInterfaces(), - ips = []; + ips = [ + 'localhost' + ]; Object.keys(ifaces).forEach(function (ifname) { ifaces[ifname].forEach(function (iface) { @@ -30,8 +31,27 @@ function getIPs() { return ips; } -// origins that always match: localhost, local IPs, etc. -whitelist = whitelist.concat(getIPs()); +function getUrls() { + var urls = [url.parse(config.url).hostname]; + + if (config.urlSSL) { + urls.push(url.parse(config.urlSSL).hostname); + } + + return urls; +} + +function getWhitelist() { + // This needs doing just one time after init + if (_.isEmpty(whitelist)) { + // origins that always match: localhost, local IPs, etc. + whitelist = whitelist.concat(getIPs()); + // Trusted urls from config.js + whitelist = whitelist.concat(getUrls()); + } + + return whitelist; +} /** * Checks the origin and enables/disables CORS headers in the response. @@ -54,7 +74,7 @@ function handleCORS(req, cb) { } // Origin matches whitelist - if (whitelist.indexOf(url.parse(origin).hostname) > -1) { + if (getWhitelist().indexOf(url.parse(origin).hostname) > -1) { return cb(null, ENABLE_CORS); } diff --git a/core/test/unit/middleware/cors_spec.js b/core/test/unit/middleware/cors_spec.js index d8da5d971b..f9facac435 100644 --- a/core/test/unit/middleware/cors_spec.js +++ b/core/test/unit/middleware/cors_spec.js @@ -1,7 +1,9 @@ /*globals describe, it, beforeEach, afterEach */ var sinon = require('sinon'), should = require('should'), - cors = require('../../../server/middleware/cors'); + rewire = require('rewire'), + configUtils = require('../../utils/configUtils'), + cors = rewire('../../../server/middleware/cors'); describe('cors', function () { var res, req, next, sandbox; @@ -31,6 +33,8 @@ describe('cors', function () { afterEach(function () { sandbox.restore(); + configUtils.restore(); + cors = rewire('../../../server/middleware/cors'); }); it('should not be enabled without a request origin header', function (done) { @@ -137,4 +141,41 @@ describe('cors', function () { done(); }); + + it('should be enabled if the origin matches config.url', function (done) { + var origin = 'http://my.blog'; + configUtils.set({ + url: origin + }); + + req.get = sinon.stub().withArgs('origin').returns(origin); + res.get = sinon.stub().withArgs('origin').returns(origin); + req.headers.origin = origin; + + cors(req, res, next); + + next.called.should.be.true(); + res.headers['Access-Control-Allow-Origin'].should.equal(origin); + + done(); + }); + + it('should be enabled if the origin matches config.urlSSL', function (done) { + var origin = 'https://secure.blog'; + configUtils.set({ + url: 'http://my.blog', + urlSSL: origin + }); + + req.get = sinon.stub().withArgs('origin').returns(origin); + res.get = sinon.stub().withArgs('origin').returns(origin); + req.headers.origin = origin; + + cors(req, res, next); + + next.called.should.be.true(); + res.headers['Access-Control-Allow-Origin'].should.equal(origin); + + done(); + }); });