Skip to content

fix: use execFile in status and logs to prevent shell interpolation of sandbox name - #281

Closed
areporeporepo wants to merge 1 commit into
NVIDIA:mainfrom
areporeporepo:fix/execfile-status-logs
Closed

fix: use execFile in status and logs to prevent shell interpolation of sandbox name#281
areporeporepo wants to merge 1 commit into
NVIDIA:mainfrom
areporeporepo:fix/execfile-status-logs

Conversation

@areporeporepo

@areporeporepo areporeporepo commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Switch exec to execFile in status.ts and logs.ts so sandbox name is passed as an argument array instead of interpolated into a shell string. Updates existing tests to match.

…f sandbox name

status.ts and logs.ts used promisify(exec) with template-literal commands,
passing sandboxName directly into a shell string. This allows shell
metacharacters in the sandbox name to be interpreted.

Switch to promisify(execFile) with argument arrays, matching the safe
pattern already used in connect.ts (spawn), onboard.ts (execFileSync),
and migrate.ts (execFileSync). execFile bypasses the shell entirely so
the sandbox name is always passed as a single argument.

Continues the hardening started in #49 and #170.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This pull request refactors command execution in the nemoclaw project to replace the exec child_process API with the safer execFile API. The change affects OpenShell commands that query sandbox state across logs and status modules, including corresponding test mocks and assertions. Control flow and functional behavior remain unchanged.

Changes

Cohort / File(s) Summary
Command implementations
nemoclaw/src/commands/logs.ts, nemoclaw/src/commands/status.ts
Replaced exec with execFile for OpenShell sandbox state queries, converting template string commands to separate program and arguments array format. Updated promisified wrapper from execAsync to execFileAsync. Timeout and JSON parsing logic preserved.
Test suite
nemoclaw/src/commands/status.test.ts
Updated test mocks and assertions to target execFile instead of exec. Renamed mock helper from mockExec to mockExecFile, adjusted routing logic to use joined argument strings, and updated all test expectations to verify execFile invocations with correct program name and argument arrays.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 From exec's shell-wrapped embrace, we hop,
To execFile's safer ground without a stop,
Arguments laid bare, no command to parse,
Sandbox queries now run with swifter grace! 🏃‍♂️✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: replacing exec with execFile to prevent shell interpolation of sandbox names, which is the primary security-focused refactoring across status.ts, logs.ts, and their tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can get early access to new features in CodeRabbit.

Enable the early_access setting to enable early access features such as new models, tools, and more.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
nemoclaw/src/commands/status.test.ts (1)

96-99: Strengthen mock routing to avoid false-positive matches.

joined.includes(substring) can accidentally match unrelated args and hide regressions. Prefer exact command-key matching (e.g., first two argv tokens).

Suggested tightening for `mockExecFile`
-    const joined = args.join(" ");
-    for (const [substring, response] of Object.entries(responses)) {
-      if (joined.includes(substring)) {
+    const commandKey = `${args[0] ?? ""} ${args[1] ?? ""}`.trim();
+    const response = responses[commandKey];
+    if (response !== undefined) {
         if (response instanceof Error) {
           callback?.(response, { stdout: "", stderr: response.message });
         } else {
           callback?.(null, { stdout: response, stderr: "" });
         }
         return;
-      }
     }
-    callback?.(new Error(`command not found: ${joined}`), { stdout: "", stderr: "" });
+    callback?.(new Error(`command not found: ${args.join(" ")}`), { stdout: "", stderr: "" });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nemoclaw/src/commands/status.test.ts` around lines 96 - 99, The mock routing
using joined.includes(substring) is too permissive and causes false-positive
matches; update the mock in mockExecFile to build a precise key from the first
two argv tokens (e.g., const key = args.slice(0,2).join(" ")) and compare that
key for exact equality against the responses entries instead of using
joined.includes(substring), ensuring responses map keys correspond to these
two-token command keys (references: joined, args, responses, mockExecFile).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@nemoclaw/src/commands/status.test.ts`:
- Around line 96-99: The mock routing using joined.includes(substring) is too
permissive and causes false-positive matches; update the mock in mockExecFile to
build a precise key from the first two argv tokens (e.g., const key =
args.slice(0,2).join(" ")) and compare that key for exact equality against the
responses entries instead of using joined.includes(substring), ensuring
responses map keys correspond to these two-token command keys (references:
joined, args, responses, mockExecFile).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c7450333-c9e1-46c8-bcd3-c27efdb4da38

📥 Commits

Reviewing files that changed from the base of the PR and between 1e23347 and 5affe38.

📒 Files selected for processing (3)
  • nemoclaw/src/commands/logs.ts
  • nemoclaw/src/commands/status.test.ts
  • nemoclaw/src/commands/status.ts

mafueee pushed a commit to mafueee/NemoClaw that referenced this pull request Mar 28, 2026
mafueee pushed a commit to mafueee/NemoClaw that referenced this pull request Mar 28, 2026
PR NVIDIA#281 removed the shared openshell-cluster Docker network in favor of
the default bridge. This restores custom bridge networking but makes each
gateway use its own isolated network named openshell-cluster-{name},
matching the existing container/volume naming convention.

Changes:
- Add network_name() to constants.rs for per-gateway network naming
- Add ensure_network() with retry/backoff and force_remove_network()
  parameterized by network name instead of a global constant
- Attach containers to their per-gateway network via network_mode
- Disconnect and remove the network during gateway destroy
- Wire ensure_network() into the deploy flow before ensure_volume()
- Update architecture docs to reflect per-gateway network isolation
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression and removed NemoClaw CLI labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants