mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Lock down theme static directory to not serve templates, markdown and text files.
closes #942 - insert custom middleware to check for blacklisted files - redirect to express.static if file accepted - if not valid return next() to do nothing - currently black listing .hbs, .txt, .md and .json - debatable which is best, black list or white list, either one will probably need tweaks but erred on side of letting a theme serve unknown types
This commit is contained in:
parent
6db7e6d96e
commit
9d114c7fa6
3 changed files with 122 additions and 2 deletions
|
@ -14,6 +14,7 @@ var express = require('express'),
|
||||||
hbs = require('express-hbs'),
|
hbs = require('express-hbs'),
|
||||||
Ghost = require('./ghost'),
|
Ghost = require('./ghost'),
|
||||||
helpers = require('./server/helpers'),
|
helpers = require('./server/helpers'),
|
||||||
|
middleware = require('./server/middleware'),
|
||||||
packageInfo = require('../package.json'),
|
packageInfo = require('../package.json'),
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
@ -187,7 +188,7 @@ function activateTheme() {
|
||||||
server.set('activeTheme', ghost.settings('activeTheme'));
|
server.set('activeTheme', ghost.settings('activeTheme'));
|
||||||
server.enable(server.get('activeTheme'));
|
server.enable(server.get('activeTheme'));
|
||||||
if (stackLocation) {
|
if (stackLocation) {
|
||||||
server.stack[stackLocation].handle = whenEnabled(server.get('activeTheme'), express['static'](ghost.paths().activeTheme));
|
server.stack[stackLocation].handle = whenEnabled(server.get('activeTheme'), middleware.staticTheme(ghost));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +260,7 @@ when(ghost.init()).then(function () {
|
||||||
server.use('/ghost', whenEnabled('admin', express['static'](path.join(__dirname, '/client/assets'))));
|
server.use('/ghost', whenEnabled('admin', express['static'](path.join(__dirname, '/client/assets'))));
|
||||||
|
|
||||||
// Theme only config
|
// Theme only config
|
||||||
server.use(whenEnabled(server.get('activeTheme'), express['static'](ghost.paths().activeTheme)));
|
server.use(whenEnabled(server.get('activeTheme'), middleware.staticTheme(ghost)));
|
||||||
|
|
||||||
// Add in all trailing slashes
|
// Add in all trailing slashes
|
||||||
server.use(slashes());
|
server.use(slashes());
|
||||||
|
|
31
core/server/middleware.js
Normal file
31
core/server/middleware.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
var _ = require('underscore'),
|
||||||
|
express = require('express'),
|
||||||
|
path = require('path');
|
||||||
|
|
||||||
|
function isBlackListedFileType(file) {
|
||||||
|
var blackListedFileTypes = ['.hbs', '.md', '.txt', '.json'],
|
||||||
|
ext = path.extname(file);
|
||||||
|
return _.contains(blackListedFileTypes, ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
var middleware = {
|
||||||
|
|
||||||
|
staticTheme: function (g) {
|
||||||
|
var ghost = g;
|
||||||
|
return function blackListStatic(req, res, next) {
|
||||||
|
if (isBlackListedFileType(req.url)) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return middleware.forwardToExpressStatic(ghost, req, res, next);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// to allow unit testing
|
||||||
|
forwardToExpressStatic: function (ghost, req, res, next) {
|
||||||
|
return express['static'](ghost.paths().activeTheme)(req, res, next);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = middleware;
|
88
core/test/unit/middleware_spec.js
Normal file
88
core/test/unit/middleware_spec.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*globals describe, beforeEach, it*/
|
||||||
|
var assert = require('assert'),
|
||||||
|
should = require('should'),
|
||||||
|
sinon = require('sinon'),
|
||||||
|
when = require('when'),
|
||||||
|
express = require('express'),
|
||||||
|
middleware = require('../../server/middleware');
|
||||||
|
|
||||||
|
describe('Middleware', function () {
|
||||||
|
describe('staticTheme', function () {
|
||||||
|
var realExpressStatic = express.static;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
sinon.stub(middleware, 'forwardToExpressStatic').yields();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
middleware.forwardToExpressStatic.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call next if hbs file type', function (done) {
|
||||||
|
var req = {
|
||||||
|
url: 'mytemplate.hbs'
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.staticTheme(null)(req, null, function (a) {
|
||||||
|
should.not.exist(a);
|
||||||
|
middleware.forwardToExpressStatic.calledOnce.should.be.false;
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call next if md file type', function (done) {
|
||||||
|
var req = {
|
||||||
|
url: 'README.md'
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.staticTheme(null)(req, null, function (a) {
|
||||||
|
should.not.exist(a);
|
||||||
|
middleware.forwardToExpressStatic.calledOnce.should.be.false;
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call next if txt file type', function (done) {
|
||||||
|
var req = {
|
||||||
|
url: 'LICENSE.txt'
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.staticTheme(null)(req, null, function (a) {
|
||||||
|
should.not.exist(a);
|
||||||
|
middleware.forwardToExpressStatic.calledOnce.should.be.false;
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call next if json file type', function (done) {
|
||||||
|
var req = {
|
||||||
|
url: 'sample.json'
|
||||||
|
}
|
||||||
|
|
||||||
|
middleware.staticTheme(null)(req, null, function (a) {
|
||||||
|
should.not.exist(a);
|
||||||
|
middleware.forwardToExpressStatic.calledOnce.should.be.false;
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call express.static if valid file type', function (done) {
|
||||||
|
var ghostStub = {
|
||||||
|
paths: function() {
|
||||||
|
return {activeTheme: 'ACTIVETHEME'};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var req = {
|
||||||
|
url: 'myvalidfile.css'
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.staticTheme(ghostStub)(req, null, function (req, res, next) {
|
||||||
|
middleware.forwardToExpressStatic.calledOnce.should.be.true;
|
||||||
|
assert.deepEqual(middleware.forwardToExpressStatic.args[0][0], ghostStub);
|
||||||
|
return done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue