diff --git a/prototype/server.js b/prototype/server.js index 0f65b96..423c892 100644 --- a/prototype/server.js +++ b/prototype/server.js @@ -19,6 +19,7 @@ const http = require('http'); const fs = require('fs'); const path = require('path'); const { exec } = require('child_process'); +const { URL } = require('url'); const PORT = 8080; const PROTOTYPE_DIR = __dirname; @@ -44,16 +45,35 @@ const MIME_TYPES = { // 创建服务器 const server = http.createServer((req, res) => { - // 解析 URL - let urlPath = req.url.split('?')[0] || '/'; + // 使用 URL 模块安全解析 URL + let urlPath; + try { + const parsedUrl = new URL(req.url, `http://${req.headers.host || 'localhost'}`); + urlPath = parsedUrl.pathname || '/'; + } catch { + urlPath = '/'; + } // 处理根路径 if (urlPath === '/') { urlPath = '/index.html'; } - // 构建文件路径 - const filePath = urlPath.startsWith("/planning-artifacts/") ? path.join(PARENT_DIR, urlPath) : path.join(PROTOTYPE_DIR, urlPath); + // 安全验证:防止路径遍历攻击 + // 规范化路径并检查是否在允许的目录内 + const isPlanningArtifacts = urlPath.startsWith("/planning-artifacts/"); + const baseDir = isPlanningArtifacts ? PARENT_DIR : PROTOTYPE_DIR; + const relativePath = isPlanningArtifacts ? urlPath : urlPath; + + const normalizedPath = path.normalize(path.join(baseDir, relativePath)); + if (!normalizedPath.startsWith(baseDir)) { + // 路径遍历攻击检测 + res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' }); + res.end('
无效的路径
'); + return; + } + + const filePath = normalizedPath; const extname = path.extname(filePath).toLowerCase(); // 设置响应头 @@ -104,16 +124,16 @@ const server = http.createServer((req, res) => {