From b832e4c8934a173d24e435a8224895525b389ffc Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2026 16:49:25 +0000 Subject: [PATCH] Fix command injection vulnerability in reconcile.ts Co-authored-by: connerkup <72580335+connerkup@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ packages/core/src/reconcile.ts | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..63d5461 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-05-14 - Fix command injection in Reconciler +**Vulnerability:** A command injection vulnerability was present in the reconciler (`packages/core/src/reconcile.ts`). The `execSync` function was used to perform syntax checking on a temporary file path with string interpolation (`node --check "${tempFile}"`). While `tempFile` itself was relatively constrained, an attacker could potentially manipulate the workspace path to inject arbitrary shell commands. +**Learning:** This codebase previously relied on `execSync` which invokes a shell interpreter, making it vulnerable to command injection if paths are not completely sanitized. Always avoid string-based command execution when user input or variable paths are involved. Furthermore, when refactoring to avoid shell usage, `execFileSync` is often a safer drop-in replacement than `spawnSync` because it preserves the exact Error object structure that existing `try...catch` blocks expect. +**Prevention:** Replaced `execSync` with `execFileSync(process.execPath, ["--check", tempFile])` which avoids shell interpretation altogether by passing arguments as an array directly to the executable. Prefer `execFileSync` over `execSync` to prevent command injection while maintaining error handling compatibility. diff --git a/packages/core/src/reconcile.ts b/packages/core/src/reconcile.ts index b0285bc..7b04b7f 100644 --- a/packages/core/src/reconcile.ts +++ b/packages/core/src/reconcile.ts @@ -1,4 +1,4 @@ -import { execSync } from "node:child_process"; +import { execFileSync } from "node:child_process"; import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; @@ -139,7 +139,7 @@ export function reconcile(options: ReconcileOptions): ReconcileResult { fs.writeFileSync(tempFile, extractedCode, "utf8"); try { - execSync(`node --check "${tempFile}"`, { stdio: "pipe" }); + execFileSync(process.execPath, ["--check", tempFile], { stdio: "pipe" }); log.audit("Syntax check passed"); } catch (err) { const stderr =