Skip to content

fix(security): disable remote uninstall execution fallback#1476

Open
Saibabu7770 wants to merge 3 commits intoNVIDIA:mainfrom
Saibabu7770:fix/uninstall-fallback-no-curl-pipe-577
Open

fix(security): disable remote uninstall execution fallback#1476
Saibabu7770 wants to merge 3 commits intoNVIDIA:mainfrom
Saibabu7770:fix/uninstall-fallback-no-curl-pipe-577

Conversation

@Saibabu7770
Copy link
Copy Markdown

@Saibabu7770 Saibabu7770 commented Apr 4, 2026

Stop executing downloaded uninstall scripts when local uninstall.sh is missing. Require manual review/download instead and add a regression guard to prevent reintroducing remote execution fallback.

Summary

Related Issue

Changes

Type of Change

  • Code change for a new feature, bug fix, or refactor.
  • Code change with doc updates.
  • Doc only. Prose changes without code sample modifications.
  • Doc only. Includes code sample changes.

Testing

  • npx prek run --all-files passes (or equivalently make check).
  • npm test passes.
  • make docs builds without warnings. (for doc-only changes)

Checklist

General

Code Changes

  • Formatters applied — npx prek run --all-files auto-fixes formatting (or make format for targeted runs).
  • Tests added or updated for new or changed behavior.
  • No secrets, API keys, or credentials committed.
  • Doc pages updated for any user-facing behavior changes (new commands, changed defaults, new features, bug fixes that contradict existing docs).

Doc Changes

  • Follows the style guide. Try running the update-docs agent skill to draft changes while complying with the style guide. For example, prompt your agent with "/update-docs catch up the docs for the new changes I made in this PR."
  • New pages include SPDX license header and frontmatter, if creating a new page.
  • Cross-references and links verified.

Signed-off-by: Your Name your-email@example.com

Summary by CodeRabbit

  • Bug Fixes

    • Uninstall now runs local-only. If no local uninstall script is found, the command exits with an error, prints instructions to manually download/review and run the remote uninstall script, and no longer automatically fetches or executes it. Help text updated to indicate "local only; no remote fallback."
  • Tests

    • Added regression test ensuring the remote uninstall fallback is disabled.

Stop executing downloaded uninstall scripts when local uninstall.sh is missing. Require manual review/download instead and add a regression guard to prevent reintroducing remote execution fallback.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

📝 Walkthrough

Walkthrough

Removed automatic remote uninstall fallback from uninstall(args); if no local uninstall.sh is found the command now prints instructions and exits with status 1. Help text updated to indicate local-only behavior. A regression test verifies the fallback is disabled.

Changes

Cohort / File(s) Summary
Uninstall CLI change
bin/nemoclaw.js
Removed code that downloaded/executed remote uninstall.sh; now aborts with an error message instructing manual download/run. Updated help() text to "local only; no remote fallback".
Regression test
test/runner.test.js
Added test uninstall fallback hardening (#577) that reads bin/nemoclaw.js and asserts removal of curl/bash remote-execution patterns and presence of the security message.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through code with careful paws,
Found a curl that flitted without pause.
Now I nudge you to fetch and read,
No secret scripts that blindly lead.
bonk Safety first — with carrot speed 🥕

🚥 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 PR title clearly and specifically describes the main security change: disabling the remote uninstall execution fallback, which is the primary objective of the changeset.

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

Actionable comments posted: 1

🤖 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/runner.test.js`:
- Around line 666-670: The test's regression guard in uninstallBlock (extracted
from "function uninstall(args)") is too narrow: update the assertions to detect
any remote execution fallback, not just the literal spawnSync("bash",
[uninstallScript...]) form. Replace the second not.toMatch with a broader regex
against uninstallBlock that matches spawnSync("bash", ...) when the argument
array contains uninstallScript (for example
/spawnSync\(\s*["']bash["']\s*,\s*\[[^\]]*uninstallScript[^\]]*\]/) and keep the
existing execFileSync("curl") check (or broaden it to
/exec(File)?Sync\(\s*["']curl["']/) so any variant that invokes curl/remote
script is caught; use the uninstallBlock and "function uninstall(args)" context
to locate where to change the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 085c13ad-8930-4fbc-8bf9-ad3f7c245e0a

📥 Commits

Reviewing files that changed from the base of the PR and between eaef339 and c06c544.

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

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.

♻️ Duplicate comments (1)
test/runner.test.js (1)

753-755: ⚠️ Potential issue | 🟠 Major

Harden this regression guard; current pattern is too narrow.

The current check only blocks the exact spawnSync("bash", [uninstallScript...]) form, so a remote fallback can be reintroduced with a different variable/signature and still pass. Also, chained split(...)[1] is brittle.

Suggested hardening
-      const uninstallBlock = src.split("function uninstall(args)")[1].split("function showStatus")[0];
-      expect(uninstallBlock).not.toMatch(/execFileSync\("curl"/);
-      expect(uninstallBlock).not.toMatch(/spawnSync\("bash", \[uninstallScript/);
+      const start = src.indexOf("function uninstall(args)");
+      const end = src.indexOf("function showStatus", start);
+      expect(start).toBeGreaterThan(-1);
+      expect(end).toBeGreaterThan(start);
+      const uninstallBlock = src.slice(start, end);
+      expect(uninstallBlock).not.toMatch(/exec(File)?Sync\(\s*["']curl["']/);
+      expect(uninstallBlock).not.toMatch(/spawnSync\(\s*["']bash["']\s*,\s*\[\s*(?!localScript\b)/);
       expect(uninstallBlock).toContain("Remote uninstall fallback is disabled for security.");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/runner.test.js` around lines 753 - 755, The current test extracts
uninstallBlock via brittle chained splits and only looks for exact patterns
execFileSync("curl" and spawnSync("bash", [uninstallScript), which is too
narrow; update the test to robustly extract the uninstall function body (e.g.,
match the function uninstall(...) { ... } block with a single regex like
/function uninstall\([^)]*\)\s*{[\s\S]*?}/) into the uninstallBlock variable and
change the assertions to reject broader remote-execution patterns such as any
exec/execFile/spawn/spawnSync/child_process usage invoking curl|wget|http(s)
URLs or invoking bash/sh with any argument that contains "uninstallScript" or an
http(s) URL; keep using uninstall and showStatus as anchors to locate the
function body and replace the two strict expect(...).not.toMatch(...) checks
with regexes that cover these wider cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@test/runner.test.js`:
- Around line 753-755: The current test extracts uninstallBlock via brittle
chained splits and only looks for exact patterns execFileSync("curl" and
spawnSync("bash", [uninstallScript), which is too narrow; update the test to
robustly extract the uninstall function body (e.g., match the function
uninstall(...) { ... } block with a single regex like /function
uninstall\([^)]*\)\s*{[\s\S]*?}/) into the uninstallBlock variable and change
the assertions to reject broader remote-execution patterns such as any
exec/execFile/spawn/spawnSync/child_process usage invoking curl|wget|http(s)
URLs or invoking bash/sh with any argument that contains "uninstallScript" or an
http(s) URL; keep using uninstall and showStatus as anchors to locate the
function body and replace the two strict expect(...).not.toMatch(...) checks
with regexes that cover these wider cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7a93459c-ae87-4ae5-9f0d-2140cf93ebb7

📥 Commits

Reviewing files that changed from the base of the PR and between c06c544 and 8426ed6.

📒 Files selected for processing (2)
  • bin/nemoclaw.js
  • test/runner.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • bin/nemoclaw.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant