Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## 2025-05-18 - Fix Command Injection in Reconciler

**Vulnerability:** Found a command injection vulnerability in `packages/core/src/reconcile.ts` where `execSync` was used to execute a shell command constructed with a file path directly from the workspace. This means if a path contains shell metacharacters (e.g. `$`, \`, quotes), it could allow arbitrary command execution during the reconcile syntax check step.

**Learning:** When executing a process using Node.js, relying on shell execution functions like `execSync` with strings that contain dynamic or user-controlled input can lead to command injection.

**Prevention:** Use array-based argument passing functions like `spawnSync` along with `process.execPath` (to prevent executing arbitrary executables in `$PATH`) instead of string-based execution functions like `execSync`.
5 changes: 3 additions & 2 deletions packages/core/src/reconcile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { execSync } from "node:child_process";
import { spawnSync } from "node:child_process";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
Expand Down Expand Up @@ -139,7 +139,8 @@ export function reconcile(options: ReconcileOptions): ReconcileResult {
fs.writeFileSync(tempFile, extractedCode, "utf8");

try {
execSync(`node --check "${tempFile}"`, { stdio: "pipe" });
const checkResult = spawnSync(process.execPath, ["--check", tempFile], { stdio: "pipe" });
if (checkResult.error || checkResult.status !== 0) { throw checkResult.error || new Error((checkResult.stderr || "").toString()); }
log.audit("Syntax check passed");
} catch (err) {
const stderr =
Expand Down
Loading