From 885ed904699c4883fa1609652afe8d35e0f59dde Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:06:25 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[CRITICAL]?= =?UTF-8?q?=20Fix=20command=20injection=20in=20reconcile=20syntax=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced `execSync` with `execFileSync` in `packages/core/src/reconcile.ts` to prevent shell command injection when checking code syntax. The workspace path is dynamic and previously was passed into a shell command template, which could allow execution of arbitrary commands if it contained shell operators. 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..b732a04 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-10-26 - Command Injection via `execSync` Path Formatting +**Vulnerability:** Command injection vulnerability identified in `packages/core/src/reconcile.ts` where a shell string was constructed using `execSync(\`node --check "\${tempFile}"\`, { stdio: "pipe" });`. Since `tempFile` derives from `options.workspace`, any shell metacharacters (e.g. `"; ;"`) within the path could lead to arbitrary command execution by the Node.js shell. +**Learning:** `execSync` passes the entire command string to the system shell. When constructing commands that include dynamic or file paths, passing it as a string allows shell injection if the dynamic parts contain unescaped shell operators. +**Prevention:** Avoid `execSync` with template strings containing dynamic paths. Instead, use `execFileSync` (or `spawnSync`) which executes the binary directly without passing the command through a shell. The arguments are passed as an array to `execFileSync`, naturally preventing any shell injections: `execFileSync(process.execPath, ["--check", tempFile], { stdio: "pipe" });`. 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 =