From aded57ff1fc68f90d8c81e557b64bb0827bfa6a9 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 22 May 2026 20:40:24 +0900 Subject: [PATCH] fix(shared): harden ripgrep-cli, zip-extractor, binary-downloader subprocess paths Same Web-Response-on-Node hazard existed in ripgrep auto-download flow, zip extraction helpers, and binary downloader streams. Switch to the new Node-safe reader and ensure no spawn path escapes as unhandledRejection. Related to #3919. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/shared/binary-downloader.ts | 9 ++++++--- src/shared/ripgrep-cli.ts | 15 +++++++++++---- .../powershell-zip-entry-listing.ts | 6 ++++-- .../zip-entry-listing/python-zip-entry-listing.ts | 6 ++++-- .../zip-entry-listing/read-zip-symlink-target.ts | 6 ++++-- .../zip-entry-listing/tar-zip-entry-listing.ts | 6 ++++-- .../zipinfo-zip-entry-listing.ts | 6 ++++-- src/shared/zip-extractor.ts | 8 +++++--- 8 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/shared/binary-downloader.ts b/src/shared/binary-downloader.ts index a44206c2e..a36c4a89a 100644 --- a/src/shared/binary-downloader.ts +++ b/src/shared/binary-downloader.ts @@ -4,6 +4,7 @@ import { spawn } from "./bun-spawn-shim"; import { bunWrite } from "./bun-file-shim"; import { validateArchiveEntries, type ArchiveEntry } from "./archive-entry-validator"; import { extractZip } from "./zip-extractor"; +import { readProcessStream } from "./process-stream-reader"; function isTarTraversalErrorOutput(output: string): boolean { return /path contains '\.\.'|member name contains '\.\.'|removing leading [`'\"]?\.\.\//i.test(output) @@ -47,7 +48,8 @@ export async function extractTarGz( const exitCode = await proc.exited; if (exitCode !== 0) { - const stderr = await new Response(proc.stderr).text(); + // #3919: Avoid Response(stream).text() in Windows Desktop utility processes. + const stderr = await readProcessStream(proc.stderr); if (isTarTraversalErrorOutput(stderr)) { throw new Error(`Unsafe archive entry: path contains path traversal (${archivePath})`) @@ -107,8 +109,9 @@ async function listTarEntries(archivePath: string, cwd?: string): Promise