fix(cli): use openshell top-level logs command#350
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughChanged the logs flag passed to Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/cli.test.js (1)
13-24: Clean up auto-created temp HOME directories inrun().When
extraEnv.HOMEis not provided,fs.mkdtempSync(...)allocates a temp directory that is never removed. Consider cleaning up internally-created homes in afinallyblock.♻️ Proposed refactor
function run(args, extraEnv = {}) { - const home = extraEnv.HOME || fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-cli-test-")); + const providedHome = extraEnv.HOME; + const home = providedHome || fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-cli-test-")); try { const out = execSync(`node "${CLI}" ${args}`, { encoding: "utf-8", timeout: 10000, env: { ...process.env, ...extraEnv, HOME: home }, }); return { code: 0, out }; } catch (err) { return { code: err.status, out: (err.stdout || "") + (err.stderr || "") }; + } finally { + if (!providedHome) { + fs.rmSync(home, { recursive: true, force: true }); + } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/cli.test.js` around lines 13 - 24, The run() helper creates a temp HOME when extraEnv.HOME is not provided but never removes it; update run to track whether HOME was created locally, wrap execSync in try/finally, and in the finally block remove the temp directory (use fs.rmSync or fs.rmdirSync with recursive:true as appropriate) only when you created it (i.e., extraEnv.HOME was falsy), preserving error/return behavior from the existing try/catch around execSync and keeping variables like home and extraEnv intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@test/cli.test.js`:
- Around line 13-24: The run() helper creates a temp HOME when extraEnv.HOME is
not provided but never removes it; update run to track whether HOME was created
locally, wrap execSync in try/finally, and in the finally block remove the temp
directory (use fs.rmSync or fs.rmdirSync with recursive:true as appropriate)
only when you created it (i.e., extraEnv.HOME was falsy), preserving
error/return behavior from the existing try/catch around execSync and keeping
variables like home and extraEnv intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 93ab0d24-ec1c-400c-b768-cc30667e6713
📒 Files selected for processing (2)
bin/nemoclaw.jstest/cli.test.js
273e829 to
35268f9
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@test/cli.test.js`:
- Around line 101-140: The test "logs dispatch uses openshell logs with tail
follow mode" creates temporary fixtures fakeBin and fakeHome but doesn't remove
them; wrap the test body (everything after creating fakeBin and fakeHome) in a
try/finally so the finally block always runs and deletes both directories (use
fs.rmSync(fakeBin, { recursive: true, force: true }) and fs.rmSync(fakeHome, {
recursive: true, force: true }) or equivalent) to ensure cleanup even if
run(...) or assertions fail; reference the variables fakeBin and fakeHome and
keep the rest of the test logic unchanged.
- Around line 101-147: The tests call assert.equal/assert.deepEqual/assert.ok
but never import Node's assert, causing a ReferenceError; fix by either
importing assert (e.g., add a top-level import/require for 'assert') or, to be
consistent with the rest of the file, replace the uses of assert in the "logs
dispatch uses openshell logs with tail follow mode" and "cleans up
internally-created HOME directories after each run" tests with Vitest expect
assertions (e.g., expect(r.code).toBe(0), expect(args).toEqual([...]),
expect(r.home).toBeTruthy(), expect(fs.existsSync(r.home)).toBe(false)); update
the calls around run(), r, and the readFileSync-derived args accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 05256fc0-b0ff-4fc2-9da2-fb22d0dc9139
📒 Files selected for processing (2)
bin/nemoclaw.jstest/cli.test.js
✅ Files skipped from review due to trivial changes (1)
- bin/nemoclaw.js
|
Addressed the remaining review items in e534924:
Verification: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/cli.test.js (1)
129-132: Usepath.delimiterfor cross-platform PATH compatibility.At line 131,
PATH: \${fakeBin}:${process.env.PATH}`uses a hardcoded POSIX delimiter. Replace withpath.delimiter` to ensure the code remains compatible if Windows support is added in the future. This pattern also appears in other test files (uninstall.test.js:43, install-preflight.test.js).Proposed patch
- const r = run("my-assistant logs --follow", { - HOME: fakeHome, - PATH: `${fakeBin}:${process.env.PATH}`, - }); + const r = run("my-assistant logs --follow", { + HOME: fakeHome, + PATH: `${fakeBin}${path.delimiter}${process.env.PATH || ""}`, + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/cli.test.js` around lines 129 - 132, The test sets the PATH env var with a hardcoded colon delimiter in the run(...) invocation (e.g., run("my-assistant logs --follow", { HOME: fakeHome, PATH: `${fakeBin}:${process.env.PATH}` })); replace the hardcoded ":" concatenation with the platform-aware path delimiter via path.delimiter (import path if missing) so PATH is built as `${fakeBin}${path.delimiter}${process.env.PATH}`; apply the same change to the other test files following this pattern (uninstall.test.js, install-preflight.test.js) to ensure cross-platform compatibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@test/cli.test.js`:
- Around line 129-132: The test sets the PATH env var with a hardcoded colon
delimiter in the run(...) invocation (e.g., run("my-assistant logs --follow", {
HOME: fakeHome, PATH: `${fakeBin}:${process.env.PATH}` })); replace the
hardcoded ":" concatenation with the platform-aware path delimiter via
path.delimiter (import path if missing) so PATH is built as
`${fakeBin}${path.delimiter}${process.env.PATH}`; apply the same change to the
other test files following this pattern (uninstall.test.js,
install-preflight.test.js) to ensure cross-platform compatibility.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2f74ba47-7e65-49d3-99a9-1c44451d96d1
📒 Files selected for processing (1)
test/cli.test.js
e534924 to
75b56d5
Compare
|
Rebased this branch onto the current |
5f92cd3 to
5d88aec
Compare
5d88aec to
d0e268a
Compare
|
Rebased by replaying the current commit stack onto the latest |
d0e268a to
85a46be
Compare
|
Replayed this branch onto the latest origin/main and preserved the intended fix: now dispatches through , while the test PATH stubs use for cross-platform safety. |
|
Replayed this branch onto the latest origin/main and preserved the intended fix: follow mode now dispatches through openshell logs with --tail, and the test PATH stubs use path.delimiter for cross-platform safety. |
|
The branch has already been replayed onto the latest @coderabbitai review |
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/cli.test.js (1)
106-133: Consider extracting sandbox fixture setup into a helper to reduce repetition.The registry JSON + fake binary setup pattern appears repeatedly in this file; a small helper would cut duplication and simplify future maintenance.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/cli.test.js` around lines 106 - 133, Multiple tests duplicate the sandbox registry + fake openshell setup (variables fakeBin, fakeHome, fakeOpenShell, registryDir and the sandboxes.json content for "my-assistant"); extract that logic into a small helper (e.g., createFakeSandboxRegistry or setupFakeOpenShell) that creates the temp dirs, writes the executable openshell script and the sandboxes.json payload (including the "my-assistant" entry and defaultSandbox), and returns the created paths so tests call the helper and perform cleanup; update existing tests to use this helper to remove repetition.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@test/cli.test.js`:
- Around line 106-133: Multiple tests duplicate the sandbox registry + fake
openshell setup (variables fakeBin, fakeHome, fakeOpenShell, registryDir and the
sandboxes.json content for "my-assistant"); extract that logic into a small
helper (e.g., createFakeSandboxRegistry or setupFakeOpenShell) that creates the
temp dirs, writes the executable openshell script and the sandboxes.json payload
(including the "my-assistant" entry and defaultSandbox), and returns the created
paths so tests call the helper and perform cleanup; update existing tests to use
this helper to remove repetition.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d3360541-cc5a-451f-97db-c4f2fef6bc16
📒 Files selected for processing (4)
bin/nemoclaw.jstest/cli.test.jstest/install-preflight.test.jstest/uninstall.test.js
✅ Files skipped from review due to trivial changes (2)
- test/uninstall.test.js
- test/install-preflight.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
- bin/nemoclaw.js
) * fix(sandbox): prevent overread request smuggling in L7 REST parser The HTTP/1.1 parser used a 1024-byte read buffer that could capture bytes from a pipelined second request. Those overflow bytes were forwarded upstream as body overflow without L7 policy evaluation, enabling request smuggling that bypasses per-request method/path enforcement. Replace multi-byte read with byte-at-a-time read_u8 that stops exactly at the CRLFCRLF header terminator. Add regression test proving two pipelined requests are parsed independently. Refs: NVIDIA#350 * fix(server): harden sandbox TLS secret volume permissions to 0400 Kubernetes secret volumes default to 0644, allowing the unprivileged sandbox user to read the mTLS client private key via the Landlock baseline /etc read set. A compromised sandbox could use the key to impersonate the control-plane client. Set defaultMode to 256 (octal 0400, owner-read only) on both the default and custom pod template paths. The supervisor reads TLS materials as root before forking, so this does not affect normal operation. Refs: NVIDIA#350 * fix(sandbox): stop using cmdline paths for binary policy matching /proc/pid/cmdline is fully attacker-controlled (argv[0] can be set to any string via execve) and had no integrity verification, unlike exec.path and ancestors which are kernel-managed and get TOFU/SHA256 checks. The Rego policy used cmdline_paths as a grant-access signal, allowing any sandboxed process to claim the identity of an allowed binary and bypass network restrictions. Remove the cmdline exact-match rule and exclude cmdline_paths from the glob-match rule. Only exec.path and exec.ancestors (from /proc/pid/exe) are now used for binary identity. cmdline_paths remain in the OPA input for deny-reason diagnostics only. Refs: NVIDIA#350 * fix(sandbox): reject symlink and non-dir read_write paths before chown The supervisor runs as root and calls chown on each read_write path. Since chown follows symlinks, a malicious container image could place a symlink (e.g. /sandbox -> /etc/shadow) to trick the supervisor into transferring ownership of arbitrary files to the sandbox user. Add symlink_metadata (lstat) check before chown to reject symlinks and non-directory entries. The TOCTOU window is not exploitable because no untrusted child process has been forked yet at this point. Refs: NVIDIA#350 * fix(server): redact provider credentials in gRPC CRUD responses Provider CRUD RPCs (create, get, list, update) returned full Provider objects including plaintext credentials (API keys, secrets). Any authenticated client -- including sandbox workloads running untrusted code -- could read credentials for all providers. Add redact_provider_credentials helper that clears the credentials map before returning. Internal server paths (inference routing, sandbox env injection) read from the store directly and are unaffected. Update tests to verify redaction and assert persistence via direct store reads. Refs: NVIDIA#350 * fix(sandbox): enforce non-root fallback when process user unset drop_privileges silently returned Ok(()) when both run_as_user and run_as_group were None, even when running as root. In local/dev mode policies are loaded from disk without passing through the server-side ensure_sandbox_process_identity normalization, so child processes could retain root and all capabilities (SYS_ADMIN, NET_ADMIN). When running as root with no process identity configured, fall back to sandbox:sandbox instead of no-oping. Non-root runtimes are unaffected. Refs: NVIDIA#350 * fix(sandbox): deny forward proxy for L7-configured endpoints The forward proxy path only performed L4 (endpoint) and allowed_ips checks. If an endpoint had L7 rules (method/path restrictions), a sandboxed process could bypass them by using HTTP_PROXY with plain http:// requests instead of CONNECT tunneling, since L7 inspection only runs in the CONNECT path. Add a guard in handle_forward_proxy that queries the endpoint's L7 config and returns 403 if any L7 rules are present, forcing traffic through the CONNECT path where per-request inspection happens. Refs: NVIDIA#350 * test(e2e): add regression test for forward proxy L7 bypass Verifies that the forward proxy path (plain http:// via HTTP_PROXY) returns 403 for endpoints with L7 rules configured, preventing sandboxed processes from bypassing per-request method/path enforcement by avoiding the CONNECT tunnel. Refs: NVIDIA#350 * fix: update tests for cmdline path and TLS volume changes Update OPA tests to verify cmdline_paths no longer grant access (regression tests for the security fix). Fix formatting in TLS volume test. Refs: NVIDIA#350 * test(e2e): update provider e2e tests for credential redaction Provider CRUD gRPC responses no longer include credential values. Update three e2e tests to assert credentials are empty in responses. Provider functionality is verified by existing e2e tests that check env var injection into sandboxes (which read from the store directly). Refs: NVIDIA#350 * chore: reformat for Rust 1.94 assert! macro style * fix(sandbox): make drop_privileges tests root-aware for CI CI runs as root but has no 'sandbox' user. The security fix correctly errors when running as root with no process identity and no fallback user available -- this is the intended behavior (refuse to run as root). Update tests to expect that error in root-without-sandbox-user environments instead of unconditionally asserting Ok. Refs: NVIDIA#350 * fix(sandbox): allow non-directory read_write entries like /dev/null The symlink guard incorrectly rejected all non-directory entries. Character devices like /dev/null are legitimate read_write paths used in sandbox policies. Only reject symlinks, which are the actual attack vector for the chown privilege escalation. Refs: NVIDIA#350
|
@WuKongAI-CMU can you fix your commits so they have verified signatures. Also need to resolve conflict with test/cli.test.js |
|
Closing — the core change this PR introduced (switching |
Fixes #253
Summary
nemoclaw <name> logs --followthroughopenshell logsinstead of the nonexistentopenshell sandbox logssubcommand--tail, matching the workaround documented in the issue commentsTest plan
Summary by CodeRabbit
Bug Fixes
Tests