From 974a4fe7bf6ff9f3de7ac260f5372631057cc9c2 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 15 Oct 2024 14:56:10 +0200 Subject: [PATCH] Handle errors for bad symlinks (#219) * Handle errors for missing symlinks * Fix test --- src/index.js | 15 ++++++++++++++- test/fixtures/symlinks/a-bad-link | 1 + test/integration.test.js | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 120000 test/fixtures/symlinks/a-bad-link diff --git a/src/index.js b/src/index.js index 34c2501..564f012 100644 --- a/src/index.js +++ b/src/index.js @@ -697,7 +697,20 @@ module.exports = async (request, response, config = {}, methods = {}) => { // resolve the symlink and run a new `stat` call just for the // target of that symlink. if (isSymLink) { - absolutePath = await handlers.realpath(absolutePath); + try { + absolutePath = await handlers.realpath(absolutePath); + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; + } + + // The requested symlink is invalid + return handlers.sendError(absolutePath, response, acceptsJSON, current, handlers, config, { + statusCode: 404, + code: 'not_found', + message: 'The requested path could not be found' + }); + } stats = await handlers.lstat(absolutePath); } diff --git a/test/fixtures/symlinks/a-bad-link b/test/fixtures/symlinks/a-bad-link new file mode 120000 index 0000000..7a904be --- /dev/null +++ b/test/fixtures/symlinks/a-bad-link @@ -0,0 +1 @@ +not-a-file \ No newline at end of file diff --git a/test/integration.test.js b/test/integration.test.js index d0e5d67..cebc479 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -1343,6 +1343,20 @@ test('allow symlinks by setting the option', async () => { expect(text).toBe(spec); }); +test('A bad symlink should be a 404', async () => { + const name = 'symlinks/a-bad-link'; + + const url = await getUrl({ + symlinks: true + }); + + const response = await fetch(`${url}/${name}`); + expect(response.status).toBe(404); + + const text = await response.text(); + expect(text.trim()).toBe('Not Found'); +}); + test('etag header is set', async () => { const url = await getUrl({ renderSingle: true,