From 12e00bf6833e2b8ca44e2056481d94fb9402d56d Mon Sep 17 00:00:00 2001 From: LukeMackin Date: Wed, 22 Jul 2026 20:12:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=89=E5=85=A8=E2=80=94=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E6=B2=99=E7=AE=B1+=E5=91=BD=E4=BB=A4=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E8=BF=87=E6=BB=A4+=E7=A7=BB=E9=99=A4unused=20spire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - safePath(): resolve→startsWith(BASE_DIR)防路径遍历 - sanitizeCommand(): 拒绝;&|$(){}等shell元字符 - 移除unused import(spawn,DeviceIdentity) --- packages/server/src/tools.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/server/src/tools.ts b/packages/server/src/tools.ts index ee7dbdd..d94eb3c 100644 --- a/packages/server/src/tools.ts +++ b/packages/server/src/tools.ts @@ -7,15 +7,24 @@ import * as fs from "node:fs"; import * as path from "node:path"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; import * as os from "node:os"; +/** Sandbox: restrict file ops to this base directory or env GCA_WORKSPACE */ +const BASE_DIR = path.resolve(process.env.GCA_WORKSPACE ?? process.cwd()); + +function safePath(p: string): string { + const resolved = path.resolve(BASE_DIR, p); + if (!resolved.startsWith(BASE_DIR)) throw new Error(`Path traversal blocked: ${p}`); + return resolved; +} + // ── C-002: file_list ──────────────────────────────────────── export async function file_list(args: { path: string; recursive?: boolean; }): Promise { - const dir = args.path || "."; + const dir = safePath(args.path || "."); const entries = fs.readdirSync(dir, { withFileTypes: true }); const result = entries.map(e => ({ name: e.name, @@ -66,11 +75,12 @@ export async function file_move(args: { } // ── C-008: exec ───────────────────────────────────────────── -export async function exec(args: { - command: string; - cwd?: string; - timeout?: number; -}): Promise { +function sanitizeCommand(cmd: string): string { + if (/[;&|`$(){}[\]<>!\\\n\r]/.test(cmd)) throw new Error(`Dangerous chars in: ${cmd.slice(0,50)}`); + return cmd; +} +export async function exec(args: { command: string; cwd?: string; timeout?: number }): Promise { + const command = sanitizeCommand(args.command); const timeout = args.timeout ?? 30000; try { const stdout = execSync(args.command, {