From b0c1d00a48899fc28d00061e4ad9d20c4a200783 Mon Sep 17 00:00:00 2001 From: harshahemanth <22571344+harshahemanth@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:03:23 -0500 Subject: [PATCH] fix: use execFile with arg arrays to prevent command injection in status exec() spawns a shell, so interpolated args like sandboxName are vulnerable to shell metacharacter injection. execFile() bypasses the shell entirely by passing args as an array directly to the process. --- nemoclaw/src/commands/status.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nemoclaw/src/commands/status.ts b/nemoclaw/src/commands/status.ts index cf594dc8d..a001673de 100644 --- a/nemoclaw/src/commands/status.ts +++ b/nemoclaw/src/commands/status.ts @@ -1,13 +1,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -import { exec } from "node:child_process"; +import { execFile } from "node:child_process"; import { existsSync } from "node:fs"; import { promisify } from "node:util"; import type { PluginLogger, NemoClawConfig } from "../index.js"; import { loadState } from "../blueprint/state.js"; -const execAsync = promisify(exec); +const execFileAsync = promisify(execFile); /** * Detect whether the plugin is running inside an OpenShell sandbox. @@ -128,7 +128,7 @@ async function getSandboxStatus(sandboxName: string, insideSandbox: boolean): Pr return { name: sandboxName, running: false, uptime: null, insideSandbox: true }; } try { - const { stdout } = await execAsync(`openshell sandbox status ${sandboxName} --json`, { + const { stdout } = await execFileAsync("openshell", ["sandbox", "status", sandboxName, "--json"], { timeout: 5000, }); const parsed = JSON.parse(stdout) as SandboxStatusResponse; @@ -162,7 +162,7 @@ async function getInferenceStatus(insideSandbox: boolean): Promise