Skip to content

fix: validate sandbox and instance names to prevent shell injection#475

Closed
areporeporepo wants to merge 2 commits intoNVIDIA:mainfrom
areporeporepo:fix/validate-sandbox-names
Closed

fix: validate sandbox and instance names to prevent shell injection#475
areporeporepo wants to merge 2 commits intoNVIDIA:mainfrom
areporeporepo:fix/validate-sandbox-names

Conversation

@areporeporepo
Copy link
Contributor

@areporeporepo areporeporepo commented Mar 20, 2026

summary

this validates sandbox and instance names before they are interpolated into shell commands.

changes

  • add validateName() in bin/lib/runner.js
  • validate names in cli dispatch, deploy, and onboard sandbox creation
  • reject invalid names early while preserving the existing valid-name path

testing

  • npm test
  • npm --prefix nemoclaw run build

checklist

  • follows conventional commits
  • commits are signed off

Summary by CodeRabbit

Release Notes

  • New Features
    • Added validation for sandbox and instance names to ensure they meet naming requirements. Invalid names are now rejected upfront with informative error messages, preventing downstream issues.

Sandbox names from user input are interpolated into shell commands
without sanitization. A malicious name with shell metacharacters
could execute arbitrary commands.

Add validateName() in runner.js that enforces [a-zA-Z0-9._-]{1,63}
and call it at all entry points: CLI dispatch, deploy, and onboard.

Signed-off-by: Anh Nguyen <29374105+aprprprr@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: anh nguyen <29374105+aprprprr@users.noreply.github.com>
@wscurran wscurran added NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). security Something isn't secure labels Mar 20, 2026
@wscurran
Copy link
Contributor

Thanks for tackling shell injection vulnerabilities by validating sandbox and instance names.

@wscurran wscurran added the priority: high Important issue that should be resolved in the next release label Mar 20, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 21, 2026

📝 Walkthrough

Walkthrough

A new name validation function was added to ensure sandbox and instance names comply with strict requirements (1–63 characters, alphanumeric start, alphanumeric plus ., _, - characters). The validator is called at two entry points in the CLI to reject invalid names early before proceeding with deployment or dispatch operations.

Changes

Cohort / File(s) Summary
Name Validation Helper
bin/lib/runner.js
Added exported validateName(name) function that validates names against regex pattern, logs error message, and exits on failure.
Validation Integration
bin/nemoclaw.js
Imported validateName and integrated it at two control-flow entry points: deploy(instanceName) before credential checks and sandbox-scoped dispatch before registry lookup.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A rabbit hops forth with a name and a plan,
But checks it twice—always the safest span!
No numbers-first chaos, no wild characters roam,
Just alphanumerics that know their way home. 🐰✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding validation for sandbox and instance names to prevent shell injection, which aligns with the changeset's primary objective.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Tip

You can customize the tone of the review comments and chat replies.

Configure the tone_instructions setting to customize the tone of the review comments and chat replies. For example, you can set the tone to Act like a strict teacher, Act like a pirate and more.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
bin/nemoclaw.js (1)

83-86: Consider consolidating regex patterns for consistency.

setup() uses a different validation pattern (/^[a-z0-9][a-z0-9-]*[a-z0-9]$/) than the new validateName(). While the value comes from the registry (so should be pre-validated), this inconsistency could lead to confusion or subtle mismatches. Consider reusing validateName() here.

Similarly, start() at lines 183-184 uses /^[a-zA-Z0-9._-]+$/ which allows names starting with ., _, or -, unlike validateName().

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/nemoclaw.js` around lines 83 - 86, The sandbox name validation is
inconsistent: replace the inline regex in setup() that builds safeName
(currently using /^[a-z0-9][a-z0-9-]*[a-z0-9]$/) with a call to the existing
validateName() helper to ensure a single canonical rule (use
registry.listSandboxes().defaultSandbox and pass it to validateName() before
assigning safeName and calling run(...)); likewise update start() to validate
the sandbox/name using validateName() instead of /^[a-zA-Z0-9._-]+$/ so names
starting with . _ - are rejected consistently; adjust safeName to an empty
string when validateName() returns false and keep the run(...) call as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@bin/nemoclaw.js`:
- Around line 83-86: The sandbox name validation is inconsistent: replace the
inline regex in setup() that builds safeName (currently using
/^[a-z0-9][a-z0-9-]*[a-z0-9]$/) with a call to the existing validateName()
helper to ensure a single canonical rule (use
registry.listSandboxes().defaultSandbox and pass it to validateName() before
assigning safeName and calling run(...)); likewise update start() to validate
the sandbox/name using validateName() instead of /^[a-zA-Z0-9._-]+$/ so names
starting with . _ - are rejected consistently; adjust safeName to an empty
string when validateName() returns false and keep the run(...) call as-is.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7094695c-8a7d-46f5-b471-a412b9096374

📥 Commits

Reviewing files that changed from the base of the PR and between 20d0c95 and 21c74f6.

📒 Files selected for processing (2)
  • bin/lib/runner.js
  • bin/nemoclaw.js

ericksoa added a commit that referenced this pull request Mar 21, 2026
Comprehensive fix for shell injection vulnerabilities where user input
(instance names, sandbox names, model names, API keys) was interpolated
unsanitized into shell commands via run()/runInteractive()/execSync().

Changes:
- Add shellQuote() and validateName() to runner.js as shared utilities
- Replace all execSync() with execFileSync() in deploy (no shell)
- Apply shellQuote() to every user-controlled variable in shell commands
  across nemoclaw.js, onboard.js, nim.js, policies.js
- Add RFC 1123 name validation at CLI dispatch for sandbox/instance names
- Fix path traversal in policies.js loadPreset()
- Replace predictable temp file with mkdtempSync()
- Remove duplicate shellQuote() definitions (now single source in runner.js)
- 9 new test cases for shellQuote, validateName, and path traversal

Supersedes #55, #110, #475, #540, #48, #171.
kjw3 pushed a commit that referenced this pull request Mar 21, 2026
* security: fix command injection across all CLI entry points

Comprehensive fix for shell injection vulnerabilities where user input
(instance names, sandbox names, model names, API keys) was interpolated
unsanitized into shell commands via run()/runInteractive()/execSync().

Changes:
- Add shellQuote() and validateName() to runner.js as shared utilities
- Replace all execSync() with execFileSync() in deploy (no shell)
- Apply shellQuote() to every user-controlled variable in shell commands
  across nemoclaw.js, onboard.js, nim.js, policies.js
- Add RFC 1123 name validation at CLI dispatch for sandbox/instance names
- Fix path traversal in policies.js loadPreset()
- Replace predictable temp file with mkdtempSync()
- Remove duplicate shellQuote() definitions (now single source in runner.js)
- 9 new test cases for shellQuote, validateName, and path traversal

Supersedes #55, #110, #475, #540, #48, #171.

* fix: deduplicate shellQuote in local-inference.js

Import shellQuote from runner.js instead of defining a local copy.
Single source of truth for shell quoting across the codebase.

* security: fix telegram bridge injection + add regression guards

Telegram bridge:
- Replace execSync with execFileSync for ssh-config retrieval
- shellQuote message, API key, and session ID in remote command
- Validate SANDBOX_NAME at startup
- Use mkdtempSync for temp SSH config (not predictable path)

Regression tests:
- nemoclaw.js must not use execSync
- Single shellQuote definition in bin/
- CLI rejects malicious sandbox names (e2e, no mocking)
- telegram-bridge.js validates SANDBOX_NAME and avoids execSync

* security: address CodeRabbit review findings on shell injection PR

- Shell-quote secret values written to .env before remote source
- Wrap scp upload in try/finally to guarantee temp secret cleanup
- Shell-quote CHAT_UI_URL and NVIDIA_API_KEY env args in onboard
- Replace predictable Date.now() temp path with mkdtempSync in policies
- Strengthen e2e test with canary file to prove payload never executes
- Fix merge-introduced test expectations for shellQuote single-quote format
jnun pushed a commit to jnun/EasyClaw that referenced this pull request Mar 21, 2026
)

* security: fix command injection across all CLI entry points

Comprehensive fix for shell injection vulnerabilities where user input
(instance names, sandbox names, model names, API keys) was interpolated
unsanitized into shell commands via run()/runInteractive()/execSync().

Changes:
- Add shellQuote() and validateName() to runner.js as shared utilities
- Replace all execSync() with execFileSync() in deploy (no shell)
- Apply shellQuote() to every user-controlled variable in shell commands
  across nemoclaw.js, onboard.js, nim.js, policies.js
- Add RFC 1123 name validation at CLI dispatch for sandbox/instance names
- Fix path traversal in policies.js loadPreset()
- Replace predictable temp file with mkdtempSync()
- Remove duplicate shellQuote() definitions (now single source in runner.js)
- 9 new test cases for shellQuote, validateName, and path traversal

Supersedes NVIDIA#55, NVIDIA#110, NVIDIA#475, NVIDIA#540, NVIDIA#48, NVIDIA#171.

* fix: deduplicate shellQuote in local-inference.js

Import shellQuote from runner.js instead of defining a local copy.
Single source of truth for shell quoting across the codebase.

* security: fix telegram bridge injection + add regression guards

Telegram bridge:
- Replace execSync with execFileSync for ssh-config retrieval
- shellQuote message, API key, and session ID in remote command
- Validate SANDBOX_NAME at startup
- Use mkdtempSync for temp SSH config (not predictable path)

Regression tests:
- nemoclaw.js must not use execSync
- Single shellQuote definition in bin/
- CLI rejects malicious sandbox names (e2e, no mocking)
- telegram-bridge.js validates SANDBOX_NAME and avoids execSync

* security: address CodeRabbit review findings on shell injection PR

- Shell-quote secret values written to .env before remote source
- Wrap scp upload in try/finally to guarantee temp secret cleanup
- Shell-quote CHAT_UI_URL and NVIDIA_API_KEY env args in onboard
- Replace predictable Date.now() temp path with mkdtempSync in policies
- Strengthen e2e test with canary file to prove payload never executes
- Fix merge-introduced test expectations for shellQuote single-quote format
@ericksoa
Copy link
Contributor

Superseded by #584 which added validateName() and shellQuote() across all CLI entry points, covering sandbox names, instance names, model names, API keys, container names, and path traversal.

@ericksoa ericksoa closed this Mar 22, 2026
Ryuketsukami pushed a commit to Ryuketsukami/NemoClaw that referenced this pull request Mar 24, 2026
)

* security: fix command injection across all CLI entry points

Comprehensive fix for shell injection vulnerabilities where user input
(instance names, sandbox names, model names, API keys) was interpolated
unsanitized into shell commands via run()/runInteractive()/execSync().

Changes:
- Add shellQuote() and validateName() to runner.js as shared utilities
- Replace all execSync() with execFileSync() in deploy (no shell)
- Apply shellQuote() to every user-controlled variable in shell commands
  across nemoclaw.js, onboard.js, nim.js, policies.js
- Add RFC 1123 name validation at CLI dispatch for sandbox/instance names
- Fix path traversal in policies.js loadPreset()
- Replace predictable temp file with mkdtempSync()
- Remove duplicate shellQuote() definitions (now single source in runner.js)
- 9 new test cases for shellQuote, validateName, and path traversal

Supersedes NVIDIA#55, NVIDIA#110, NVIDIA#475, NVIDIA#540, NVIDIA#48, NVIDIA#171.

* fix: deduplicate shellQuote in local-inference.js

Import shellQuote from runner.js instead of defining a local copy.
Single source of truth for shell quoting across the codebase.

* security: fix telegram bridge injection + add regression guards

Telegram bridge:
- Replace execSync with execFileSync for ssh-config retrieval
- shellQuote message, API key, and session ID in remote command
- Validate SANDBOX_NAME at startup
- Use mkdtempSync for temp SSH config (not predictable path)

Regression tests:
- nemoclaw.js must not use execSync
- Single shellQuote definition in bin/
- CLI rejects malicious sandbox names (e2e, no mocking)
- telegram-bridge.js validates SANDBOX_NAME and avoids execSync

* security: address CodeRabbit review findings on shell injection PR

- Shell-quote secret values written to .env before remote source
- Wrap scp upload in try/finally to guarantee temp secret cleanup
- Shell-quote CHAT_UI_URL and NVIDIA_API_KEY env args in onboard
- Replace predictable Date.now() temp path with mkdtempSync in policies
- Strengthen e2e test with canary file to prove payload never executes
- Fix merge-introduced test expectations for shellQuote single-quote format
jessesanford pushed a commit to jessesanford/NemoClaw that referenced this pull request Mar 24, 2026
)

* security: fix command injection across all CLI entry points

Comprehensive fix for shell injection vulnerabilities where user input
(instance names, sandbox names, model names, API keys) was interpolated
unsanitized into shell commands via run()/runInteractive()/execSync().

Changes:
- Add shellQuote() and validateName() to runner.js as shared utilities
- Replace all execSync() with execFileSync() in deploy (no shell)
- Apply shellQuote() to every user-controlled variable in shell commands
  across nemoclaw.js, onboard.js, nim.js, policies.js
- Add RFC 1123 name validation at CLI dispatch for sandbox/instance names
- Fix path traversal in policies.js loadPreset()
- Replace predictable temp file with mkdtempSync()
- Remove duplicate shellQuote() definitions (now single source in runner.js)
- 9 new test cases for shellQuote, validateName, and path traversal

Supersedes NVIDIA#55, NVIDIA#110, NVIDIA#475, NVIDIA#540, NVIDIA#48, NVIDIA#171.

* fix: deduplicate shellQuote in local-inference.js

Import shellQuote from runner.js instead of defining a local copy.
Single source of truth for shell quoting across the codebase.

* security: fix telegram bridge injection + add regression guards

Telegram bridge:
- Replace execSync with execFileSync for ssh-config retrieval
- shellQuote message, API key, and session ID in remote command
- Validate SANDBOX_NAME at startup
- Use mkdtempSync for temp SSH config (not predictable path)

Regression tests:
- nemoclaw.js must not use execSync
- Single shellQuote definition in bin/
- CLI rejects malicious sandbox names (e2e, no mocking)
- telegram-bridge.js validates SANDBOX_NAME and avoids execSync

* security: address CodeRabbit review findings on shell injection PR

- Shell-quote secret values written to .env before remote source
- Wrap scp upload in try/finally to guarantee temp secret cleanup
- Shell-quote CHAT_UI_URL and NVIDIA_API_KEY env args in onboard
- Replace predictable Date.now() temp path with mkdtempSync in policies
- Strengthen e2e test with canary file to prove payload never executes
- Fix merge-introduced test expectations for shellQuote single-quote format
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). priority: high Important issue that should be resolved in the next release security Something isn't secure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants