[object Object]

← back to Glassbeadedwallpaper

Harden static file server against path traversal and malformed URLs

52d382ed4a99ae505c8bf20e001b7375dfc0d436 · 2026-05-18 20:36:06 -0700 · Steve

Files touched

Diff

commit 52d382ed4a99ae505c8bf20e001b7375dfc0d436
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon May 18 20:36:06 2026 -0700

    Harden static file server against path traversal and malformed URLs
---
 server.js | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/server.js b/server.js
index 682fc37..81e7431 100644
--- a/server.js
+++ b/server.js
@@ -100,10 +100,25 @@ const server = http.createServer((req, res) => {
     res.setHeader('Expires', '0');
 
     // Remove query string parameters from URL
-    let requestPath = req.url.split('?')[0];
-    let filePath = '.' + requestPath;
-    if (filePath === './') {
-        filePath = './index.html';
+    let requestPath;
+    try {
+        requestPath = decodeURIComponent(req.url.split('?')[0]);
+    } catch (e) {
+        res.writeHead(400, { 'Content-Type': 'text/html' });
+        res.end('<h1>400 - Bad Request</h1>', 'utf-8');
+        return;
+    }
+    if (requestPath === '/') {
+        requestPath = '/index.html';
+    }
+
+    // Resolve against the project root and reject any path that escapes it
+    const rootDir = __dirname;
+    const filePath = path.join(rootDir, requestPath);
+    if (filePath !== rootDir && !filePath.startsWith(rootDir + path.sep)) {
+        res.writeHead(403, { 'Content-Type': 'text/html' });
+        res.end('<h1>403 - Forbidden</h1>', 'utf-8');
+        return;
     }
 
     const extname = String(path.extname(filePath)).toLowerCase();

← 11aa7e9 Add rel=noopener noreferrer to external target=_blank links  ·  back to Glassbeadedwallpaper  ·  add corner-nav.js — universal top-right nav per _shared/corn f4bc87c →