Skip to content

fix(onboard): reject sandbox names that collide with global CLI commands#1773

Merged
cv merged 3 commits intoNVIDIA:mainfrom
latenighthackathon:fix/reserved-sandbox-names
Apr 14, 2026
Merged

fix(onboard): reject sandbox names that collide with global CLI commands#1773
cv merged 3 commits intoNVIDIA:mainfrom
latenighthackathon:fix/reserved-sandbox-names

Conversation

@latenighthackathon
Copy link
Copy Markdown
Contributor

@latenighthackathon latenighthackathon commented Apr 11, 2026

Summary

Sandbox names that match global CLI commands (e.g. 'status', 'list', 'debug') are now rejected during onboarding with a clear error message.

Problem

If a user names their sandbox 'status', running nemoclaw status connect routes to the global status command instead of the sandbox. The sandbox becomes inaccessible via normal CLI workflows since the global command always takes routing priority.

Fix

Add a reserved-name check in promptValidatedSandboxName() after RFC 1123 validation passes. Names matching any entry in the global commands set (onboard, list, deploy, setup, start, stop, status, debug, uninstall, credentials, help) are rejected with a prompt to choose a different name. In non-interactive mode, this exits with code 1 (existing behavior for invalid names).

Test plan

  • npm run build:cli passes
  • npm run typecheck:cli passes
  • npm run lint passes
  • Existing digit-rejection test still passes
  • All onboard tests pass (1 pre-existing timeout)

Closes #1731

Signed-off-by: latenighthackathon latenighthackathon@users.noreply.github.com

Summary by CodeRabbit

  • Bug Fixes
    • Sandbox name validation now rejects names that match reserved CLI commands (e.g., status, list, deploy, help) and displays a clear error.
    • Non-interactive sandbox creation now terminates immediately on reserved-name errors; interactive flows show the error and allow retrying until attempts are exhausted.

A sandbox named 'status', 'list', or 'debug' becomes inaccessible
because the CLI router matches global commands before sandbox names.
Add a reserved-name check in promptValidatedSandboxName that rejects
names matching any global command and prompts the user to choose a
different name.

Closes NVIDIA#1731

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 60930ac9-e00d-4526-8a04-b1637987b4a0

📥 Commits

Reviewing files that changed from the base of the PR and between adea843 and 6c85e74.

📒 Files selected for processing (1)
  • src/lib/onboard.ts
✅ Files skipped from review due to trivial changes (1)
  • src/lib/onboard.ts

📝 Walkthrough

Walkthrough

The promptValidatedSandboxName() function now rejects sandbox names that exactly match a hardcoded set of NemoClaw global CLI commands (e.g., status, list, deploy, help), printing errors and treating them as invalid; other validation and attempt-limit behavior remain unchanged.

Changes

Cohort / File(s) Summary
Sandbox Name Validation
src/lib/onboard.ts
Added a RESERVED_NAMES check inside promptValidatedSandboxName() that rejects exact matches to reserved global CLI commands: status, list, deploy, help, debug, start, stop, onboard, setup, uninstall, credentials. On reserved-name entry the function prints reservation/routing-conflict errors and fails validation (exits in non-interactive mode or prompts to retry).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibble keys and hop through code,
I block the names that overload,
"status", "list", "help" must not collide,
Now sandbox names and commands divide.
🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: rejecting sandbox names that match global CLI commands to prevent routing conflicts.
Linked Issues check ✅ Passed The PR implements the core requirement from issue #1731: rejecting sandbox names matching global CLI commands (status, list, deploy, setup, start, stop, onboard, debug, uninstall, credentials, help) with appropriate error handling.
Out of Scope Changes check ✅ Passed All changes are scoped to the promptValidatedSandboxName() function to add reserved-name validation after RFC 1123 validation, directly addressing issue #1731 with no unrelated modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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.

Copy link
Copy Markdown
Contributor

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/onboard.ts (1)

2244-2258: ⚠️ Potential issue | 🟡 Minor

Avoid showing RFC-1123 format errors for reserved names.

When RESERVED_NAMES.has(sandboxName) is true, execution falls through and also prints the generic invalid-format message at Line 2252-Line 2258. That creates conflicting guidance for a syntactically valid-but-reserved name.

Suggested fix
     if (/^[a-z]([a-z0-9-]*[a-z0-9])?$/.test(sandboxName)) {
       // Reject names that collide with global CLI commands.
@@
       if (RESERVED_NAMES.has(sandboxName)) {
         console.error(`  Reserved name: '${sandboxName}' is a NemoClaw CLI command.`);
         console.error("  Choose a different name to avoid routing conflicts.");
+        if (isNonInteractive()) {
+          process.exit(1);
+        }
+        if (attempt < MAX_ATTEMPTS - 1) {
+          console.error("  Please try again.\n");
+        }
+        continue;
       } else {
         return sandboxName;
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard.ts` around lines 2244 - 2258, The reserved-name branch logs
that the name is a CLI command but then falls through and also prints the
generic "Invalid sandbox name" format errors; update the RESERVED_NAMES handling
so it exits the validation early (e.g., after the two console.error calls inside
the if (RESERVED_NAMES.has(sandboxName)) block) by returning a sentinel
(undefined/null) or otherwise breaking out (or continue if inside a loop) so the
subsequent invalid-format checks for sandboxName are not executed; refer to
RESERVED_NAMES and sandboxName in the validation block in src/lib/onboard.ts and
ensure the branch stops further validation messages.
🧹 Nitpick comments (1)
src/lib/onboard.ts (1)

2239-2243: Prefer a single source of truth for reserved command names.

RESERVED_NAMES duplicates command definitions from src/nemoclaw.ts (GLOBAL_COMMANDS, Line 72-Line 88 in the provided snippet). This will drift when new global commands are added.

Refactor direction
-      const RESERVED_NAMES = new Set([
-        "onboard", "list", "deploy", "setup", "setup-spark",
-        "start", "stop", "status", "debug", "uninstall",
-        "credentials", "help",
-      ]);
+      const RESERVED_NAMES = GLOBAL_COMMANDS_FOR_SANDBOX_NAMES;

Move the command list to a shared module (e.g., src/lib/cli-commands.ts) and consume it from both command routing and onboarding validation.

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

In `@src/lib/onboard.ts` around lines 2239 - 2243, RESERVED_NAMES in onboard.ts
duplicates the global command list defined as GLOBAL_COMMANDS; extract the
canonical array/set of command names into a single exported constant (e.g.,
CLI_COMMAND_NAMES) in a new shared module and replace both RESERVED_NAMES and
the source of GLOBAL_COMMANDS to import that single constant, then update
onboarding validation to build a Set from that import (or export the Set
directly) so both command routing (GLOBAL_COMMANDS) and onboarding use the same
source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/lib/onboard.ts`:
- Around line 2244-2258: The reserved-name branch logs that the name is a CLI
command but then falls through and also prints the generic "Invalid sandbox
name" format errors; update the RESERVED_NAMES handling so it exits the
validation early (e.g., after the two console.error calls inside the if
(RESERVED_NAMES.has(sandboxName)) block) by returning a sentinel
(undefined/null) or otherwise breaking out (or continue if inside a loop) so the
subsequent invalid-format checks for sandboxName are not executed; refer to
RESERVED_NAMES and sandboxName in the validation block in src/lib/onboard.ts and
ensure the branch stops further validation messages.

---

Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 2239-2243: RESERVED_NAMES in onboard.ts duplicates the global
command list defined as GLOBAL_COMMANDS; extract the canonical array/set of
command names into a single exported constant (e.g., CLI_COMMAND_NAMES) in a new
shared module and replace both RESERVED_NAMES and the source of GLOBAL_COMMANDS
to import that single constant, then update onboarding validation to build a Set
from that import (or export the Set directly) so both command routing
(GLOBAL_COMMANDS) and onboarding use the same source of truth.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e9e9f25c-4921-4c75-8649-b3e327abc299

📥 Commits

Reviewing files that changed from the base of the PR and between 035144e and f078f7e.

📒 Files selected for processing (1)
  • src/lib/onboard.ts

When a reserved name like 'status' was rejected, execution fell through
to the generic 'Invalid sandbox name' error, showing conflicting
guidance. Now reserved names exit immediately in non-interactive mode,
show 'Please try again' in interactive mode, and skip the generic error.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@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)
src/lib/onboard.ts (1)

2239-2243: Centralize the reserved command list to prevent drift.

RESERVED_NAMES duplicates the router’s global command source (src/nemoclaw.ts, GLOBAL_COMMANDS). If one list changes without the other, onboarding can regress and allow new collisions again. Prefer sharing one exported constant/module used by both paths.

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

In `@src/lib/onboard.ts` around lines 2239 - 2243, RESERVED_NAMES duplicates
GLOBAL_COMMANDS; export a single shared constant (e.g., export const
GLOBAL_COMMANDS or RESERVED_COMMANDS) from a common module and import it where
needed instead of redefining RESERVED_NAMES in onboard.ts; update references in
onboard.ts to use the imported symbol (RESERVED_NAMES -> GLOBAL_COMMANDS or vice
versa) and remove the local Set declaration so both the router and onboarding
use the same source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 2239-2243: RESERVED_NAMES duplicates GLOBAL_COMMANDS; export a
single shared constant (e.g., export const GLOBAL_COMMANDS or RESERVED_COMMANDS)
from a common module and import it where needed instead of redefining
RESERVED_NAMES in onboard.ts; update references in onboard.ts to use the
imported symbol (RESERVED_NAMES -> GLOBAL_COMMANDS or vice versa) and remove the
local Set declaration so both the router and onboarding use the same source of
truth.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e44f9a2d-c5bc-4245-8463-f4ca569dfeb7

📥 Commits

Reviewing files that changed from the base of the PR and between f078f7e and adea843.

📒 Files selected for processing (1)
  • src/lib/onboard.ts

@wscurran wscurran added bug Something isn't working NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). labels Apr 13, 2026
@wscurran
Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this PR, which proposes a fix for a bug where sandbox names that match global CLI commands are not rejected during onboarding .


Possibly related open issues:

@cv cv added the v0.0.16 Release target label Apr 14, 2026
@cv cv merged commit 65d7e86 into NVIDIA:main Apr 14, 2026
1 check passed
cv pushed a commit that referenced this pull request Apr 14, 2026
## Summary
- Document tier-based policy selector (Restricted/Balanced/Open) in
commands, network policies, and customize-network-policy pages (from
#1753)
- Document configurable port overrides via environment variables
(`NEMOCLAW_GATEWAY_PORT`, `NEMOCLAW_DASHBOARD_PORT`,
`NEMOCLAW_VLLM_PORT`, `NEMOCLAW_OLLAMA_PORT`) (from #1645)
- Document `nemoclaw <sandbox> skill install <path>` command (from
#1845, #1856)
- Document reserved sandbox name validation — CLI command collision
check (from #1773)
- Bump doc version switcher through 0.0.15
- Remove `--dangerously-skip-permissions` from onboard usage synopsis
(docs-skip violation)
- Regenerate agent skills from updated docs

## Test plan
- [x] `make docs` builds without warnings
- [x] All pre-commit hooks pass
- [ ] Verify rendered pages in docs build output
- [ ] Cross-references resolve correctly (`policy-tiers` anchor,
`environment-variables` section)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). v0.0.16 Release target

Projects

None yet

3 participants