From fcfedf1ae06250a9106262769af7d2ce6038aecc Mon Sep 17 00:00:00 2001 From: LukeMackin Date: Wed, 22 Jul 2026 20:19:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=89=E5=85=A8CRITICAL=E2=80=94exec?= =?UTF-8?q?=E7=94=A8=E5=87=80=E5=8C=96=E5=91=BD=E4=BB=A4+file=5Fread/write?= =?UTF-8?q?/move=E5=85=A8=E5=8A=A0safePath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/server/src/tools.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/server/src/tools.ts b/packages/server/src/tools.ts index d94eb3c..8b7a6ed 100644 --- a/packages/server/src/tools.ts +++ b/packages/server/src/tools.ts @@ -19,7 +19,7 @@ function safePath(p: string): string { return resolved; } -// ── C-002: file_list ──────────────────────────────────────── +// 鈹€鈹€ C-002: file_list 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ export async function file_list(args: { path: string; recursive?: boolean; @@ -34,7 +34,7 @@ export async function file_list(args: { return { path: dir, entries: result, count: result.length }; } -// ── C-003: file_read ──────────────────────────────────────── +// 鈹€鈹€ C-003: file_read 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ export async function file_read(args: { path: string; encoding?: string; @@ -42,17 +42,17 @@ export async function file_read(args: { limit?: number; }): Promise { const encoding = (args.encoding === "base64" ? "base64" : "utf8") as BufferEncoding; - let content = fs.readFileSync(args.path, encoding); + let content = fs.readFileSync(safePath(args.path, encoding); if (encoding === "utf8") { const lines = (content as string).split("\n"); const start = args.offset ?? 0; const end = args.limit ? start + args.limit : lines.length; content = lines.slice(start, end).join("\n"); } - return { path: args.path, content, size: fs.statSync(args.path).size }; + return { path: args.path, content, size: fs.statSync(safePath(args.path).size }; } -// ── C-004: file_write ─────────────────────────────────────── +// 鈹€鈹€ C-004: file_write 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ export async function file_write(args: { path: string; content: string; @@ -60,21 +60,21 @@ export async function file_write(args: { }): Promise { const encoding = args.encoding === "base64" ? "base64" : "utf8"; fs.mkdirSync(path.dirname(args.path), { recursive: true }); - fs.writeFileSync(args.path, args.content, encoding as BufferEncoding); - return { ok: true, path: args.path, size: fs.statSync(args.path).size }; + fs.writeFileSync(safePath(args.path, args.content, encoding as BufferEncoding); + return { ok: true, path: args.path, size: fs.statSync(safePath(args.path).size }; } -// ── C-005: file_move ──────────────────────────────────────── +// 鈹€鈹€ C-005: file_move 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ export async function file_move(args: { from: string; to: string; }): Promise { - fs.mkdirSync(path.dirname(args.to), { recursive: true }); - fs.renameSync(args.from, args.to); + fs.mkdirSync(path.dirname(safePath(args.to)), { recursive: true }); + fs.renameSync(safePath(args.from, args.to); return { ok: true, from: args.from, to: args.to }; } -// ── C-008: exec ───────────────────────────────────────────── +// 鈹€鈹€ C-008: exec 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ function sanitizeCommand(cmd: string): string { if (/[;&|`$(){}[\]<>!\\\n\r]/.test(cmd)) throw new Error(`Dangerous chars in: ${cmd.slice(0,50)}`); return cmd; @@ -83,7 +83,7 @@ export async function exec(args: { command: string; cwd?: string; timeout?: numb const command = sanitizeCommand(args.command); const timeout = args.timeout ?? 30000; try { - const stdout = execSync(args.command, { + const stdout = execSync(command, { cwd: args.cwd ?? process.cwd(), timeout, encoding: "utf8", @@ -102,7 +102,7 @@ export async function exec(args: { command: string; cwd?: string; timeout?: numb } } -// ── C-010: process_list ───────────────────────────────────── +// 鈹€鈹€ C-010: process_list 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ export async function process_list(args: { filter?: string; }): Promise { @@ -133,7 +133,7 @@ export async function process_list(args: { return { count: filtered.length, processes: filtered }; } -// ── C-011: sysinfo ────────────────────────────────────────── +// 鈹€鈹€ C-011: sysinfo 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€ export async function sysinfo(_args: {}): Promise { const cpuUsage = os.loadavg(); const totalMem = os.totalmem();