diff --git a/lib/directory.js b/lib/directory.js index 2162d15..9a2a602 100755 --- a/lib/directory.js +++ b/lib/directory.js @@ -64,7 +64,12 @@ exports.handler = function (route, options) { // Append parameter - const selection = request.params[paramName]; + const selection = request.params[paramName] || ''; + + if (Path.isAbsolute(selection)) { + throw Boom.notFound(null, {}); + } + if (selection && !settings.showHidden && internals.isFileHidden(selection)) { @@ -93,7 +98,7 @@ exports.handler = function (route, options) { fileOptions.confine = baseDir; - let path = selection || ''; + let path = selection; let error; try { diff --git a/test/security.js b/test/security.js index f35f308..a961448 100755 --- a/test/security.js +++ b/test/security.js @@ -87,6 +87,32 @@ describe('security', () => { expect(res.statusCode).to.equal(404); }); + it('blocks absolute paths at top level path', async () => { + + const server = await provisionServer(); + server.route({ method: 'GET', path: '/{path*}', handler: { directory: { path: './' } } }); + + // Confirm success with relative path + const resRel = await server.inject('/directory.js'); + expect(resRel.statusCode).to.equal(200); + + const resAbs = await server.inject(`/${require.resolve('./directory.js')}`); + expect(resAbs.statusCode).to.equal(404); + }); + + it('blocks absolute paths non-top level path', async () => { + + const server = await provisionServer(); + server.route({ method: 'GET', path: '/directory/{path*}', handler: { directory: { path: './' } } }); + + // Confirm success with relative path + const resRel = await server.inject('/directory/directory.js'); + expect(resRel.statusCode).to.equal(200); + + const resAbs = await server.inject(`/directory/${require.resolve('./directory.js')}`); + expect(resAbs.statusCode).to.equal(404); + }); + it('blocks access to files outside of base directory for file handler', async () => { const server = await provisionServer();