From 876a53c4718e75f00b89f5aa26147e48eca85889 Mon Sep 17 00:00:00 2001 From: vaibhavmashal Date: Tue, 8 Sep 2026 22:15:42 +0530 Subject: [PATCH] feat: add followSymlinks option to configure symlink traversal (#120) --- README.md | 5 +++++ index.js | 3 +++ test/test.js | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/README.md b/README.md index 3ff1f1fa..429a79e1 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,11 @@ all methods. The default value is `true`. +##### followSymlinks + +Enable or disable following symbolic links, defaults to `true`. Set to `false` +to restrict symlink traversal outside root. + ##### immutable Enable or disable the `immutable` directive in the `Cache-Control` response diff --git a/index.js b/index.js index 1bee4637..055217c5 100644 --- a/index.js +++ b/index.js @@ -60,6 +60,9 @@ function serveStatic (root, options) { } // setup options for send + opts.followSymlinks = opts.followSymlinks !== undefined + ? opts.followSymlinks + : true opts.maxage = opts.maxage || opts.maxAge || 0 opts.root = resolve(root) diff --git a/test/test.js b/test/test.js index 9933eed1..66223563 100644 --- a/test/test.js +++ b/test/test.js @@ -398,6 +398,30 @@ describe('serveStatic()', function () { }) }) + describe('followSymlinks', function () { + it('should default to true', function (done) { + request(createServer(fixtures)) + .get('/todo.txt') + .expect(200, '- groceries', done) + }) + + describe('when false', function () { + it('should accept followSymlinks: false', function (done) { + request(createServer(fixtures, { followSymlinks: false })) + .get('/todo.txt') + .expect(200, '- groceries', done) + }) + }) + + describe('when true', function () { + it('should accept followSymlinks: true', function (done) { + request(createServer(fixtures, { followSymlinks: true })) + .get('/todo.txt') + .expect(200, '- groceries', done) + }) + }) + }) + describe('hidden files', function () { var server before(function () {