fix(policy): restrict baseline npm_registry to openclaw binary only#1700
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:
📝 WalkthroughWalkthroughRestricted the Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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.
Pull request overview
Updates the baseline OpenClaw sandbox network policy so that “none” onboarding no longer permits agent-driven npm install egress to registry.npmjs.org, while keeping plugin installation working via the openclaw CLI.
Changes:
- Removed
/usr/local/bin/npmand/usr/local/bin/nodefrom the baselinenpm_registrypolicy’s allowed binaries. - Clarified inline policy comments to document that
npm_registryis intended foropenclaw plugins installonly and references issue #1458.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # npm registry — needed for `openclaw plugins install` only. | ||
| # Restricted to the openclaw binary so agents cannot use npm directly. | ||
| # Users who need npm/node access should add the npm policy preset during onboard. | ||
| # Ref: https://github.com/NVIDIA/NemoClaw/issues/1458 | ||
| npm_registry: | ||
| name: npm_registry |
There was a problem hiding this comment.
The documentation tables still describe the baseline npm_registry policy as allowing /usr/local/bin/npm and /usr/local/bin/node (and even “All methods”), but the baseline policy is now restricted to /usr/local/bin/openclaw with GET-only. Please update docs/reference/network-policies.md and .agents/skills/nemoclaw-user-reference/references/network-policies.md to match this policy change so users aren’t misled.
| @@ -205,8 +207,6 @@ network_policies: | |||
| - allow: { method: GET, path: "/**" } | |||
| binaries: | |||
| - { path: /usr/local/bin/openclaw } | |||
There was a problem hiding this comment.
Given this is a security regression fix (#1458), consider adding a small regression test that asserts the baseline npm_registry binaries list does not include npm/node (e.g., in test/validate-blueprint.test.ts). That will prevent accidental reintroduction of agent npm egress in future edits.
- Update docs/reference/network-policies.md: npm_registry now shows openclaw-only binary and GET-only access (not npm/node + all methods) - Update .agents/skills/nemoclaw-user-reference/references/network-policies.md with the same correction - Add regression test in validate-blueprint.test.ts (NVIDIA#1458): asserts that /usr/local/bin/npm and /usr/local/bin/node are not in the baseline npm_registry binaries list to prevent reintroduction of agent npm egress Per Copilot review on NVIDIA#1700. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
|
Addressed both review points:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
test/validate-blueprint.test.ts (1)
192-204: Strengthen the regression test to enforce an exact allowlist.Current assertions still pass if another unexpected binary gets added. Consider asserting the final list is exactly
openclaw.Suggested test hardening
- const paths = (binaries ?? []).map((b) => b.path); + const paths = (binaries ?? []).map((b) => b.path).sort(); @@ - expect(paths).not.toContain("/usr/local/bin/npm"); - expect(paths).not.toContain("/usr/local/bin/node"); - expect(paths).toContain("/usr/local/bin/openclaw"); + expect(paths).toEqual(["/usr/local/bin/openclaw"]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/validate-blueprint.test.ts` around lines 192 - 204, The test "regression `#1458`: baseline npm_registry must not include npm or node binaries" currently checks only that npm/node are absent and openclaw is present; change it to enforce an exact allowlist by asserting that the computed paths (from np, npm_registry, binaries, paths) equal exactly ['/usr/local/bin/openclaw'] (use a strict equality assertion such as toEqual/toStrictEqual) so no other unexpected binaries are allowed; replace or augment the existing expect(...) checks with a single exact-match assertion on paths.docs/reference/network-policies.md (1)
93-94: Format the CLI command as inline code in the table cell.In Line 93,
openclaw plugins installis a CLI command in prose; wrap it in inline code.Suggested doc fix
- - `/usr/local/bin/openclaw` only (openclaw plugins install) + - `/usr/local/bin/openclaw` only (`openclaw plugins install`)As per coding guidelines, “CLI commands, file paths, flags, parameter names, and values must use inline
codeformatting,” and word-list casing checks are exempt inside code spans.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/reference/network-policies.md` around lines 93 - 94, Wrap the inline CLI command and any file paths in code formatting: replace the plain text "openclaw plugins install" and "/usr/local/bin/openclaw" in the table cell with inline code spans (e.g., `openclaw plugins install` and `/usr/local/bin/openclaw`) so they follow the guideline that CLI commands, file paths, flags, parameter names, and values use inline code formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/nemoclaw-user-reference/references/network-policies.md:
- Around line 71-72: This change edited an autogenerated skill doc under the
.agents/skills/nemoclaw-user-* tree; revert the direct edit and instead make the
content change in the source docs (docs/), then regenerate the skill markdown
using the generator script so the update is not lost: update the relevant file
in docs/, run python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix
nemoclaw-user to produce refreshed .agents/skills/nemoclaw-user-*.md files, and
commit the regenerated artifacts (do not edit .agents/skills/nemoclaw-user-*.md
by hand).
---
Nitpick comments:
In `@docs/reference/network-policies.md`:
- Around line 93-94: Wrap the inline CLI command and any file paths in code
formatting: replace the plain text "openclaw plugins install" and
"/usr/local/bin/openclaw" in the table cell with inline code spans (e.g.,
`openclaw plugins install` and `/usr/local/bin/openclaw`) so they follow the
guideline that CLI commands, file paths, flags, parameter names, and values use
inline code formatting.
In `@test/validate-blueprint.test.ts`:
- Around line 192-204: The test "regression `#1458`: baseline npm_registry must
not include npm or node binaries" currently checks only that npm/node are absent
and openclaw is present; change it to enforce an exact allowlist by asserting
that the computed paths (from np, npm_registry, binaries, paths) equal exactly
['/usr/local/bin/openclaw'] (use a strict equality assertion such as
toEqual/toStrictEqual) so no other unexpected binaries are allowed; replace or
augment the existing expect(...) checks with a single exact-match assertion on
paths.
🪄 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: 1e544d00-127e-442d-b1e2-a4ac6efe093b
📒 Files selected for processing (3)
.agents/skills/nemoclaw-user-reference/references/network-policies.mddocs/reference/network-policies.mdtest/validate-blueprint.test.ts
- Revert direct edit of .agents/skills/ and regenerate via scripts/docs-to-skills.py as required by coding guidelines - Tighten regression test: use exact allowlist (toEqual) instead of not.toContain to catch any future unexpected binary additions Per CodeRabbit review on NVIDIA#1700. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
|
Addressed both CodeRabbit points:
|
|
✨ Thanks for submitting this PR, which proposes a fix for an issue with the baseline npm registry policy and may improve the overall security of the system. Possibly related open issues: |
a66ba34 to
c5cdb39
Compare
- Update docs/reference/network-policies.md: npm_registry now shows openclaw-only binary and GET-only access (not npm/node + all methods) - Update .agents/skills/nemoclaw-user-reference/references/network-policies.md with the same correction - Add regression test in validate-blueprint.test.ts (NVIDIA#1458): asserts that /usr/local/bin/npm and /usr/local/bin/node are not in the baseline npm_registry binaries list to prevent reintroduction of agent npm egress Per Copilot review on NVIDIA#1700. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
The baseline policy allowed /usr/local/bin/npm and /usr/local/bin/node to reach registry.npmjs.org. This meant npm install worked even with 'none' policy preset selected during onboard — violating user intent. The npm_registry entry in the baseline exists for 'openclaw plugins install' only, not for agent-driven npm usage. Removing npm/node from the binaries list so only the openclaw CLI binary can reach the npm registry by default. Users who need npm/node access in the sandbox should add the 'npm' preset during onboard or via nemoclaw policy. Fixes NVIDIA#1458 Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
- Update docs/reference/network-policies.md: npm_registry now shows openclaw-only binary and GET-only access (not npm/node + all methods) - Update .agents/skills/nemoclaw-user-reference/references/network-policies.md with the same correction - Add regression test in validate-blueprint.test.ts (NVIDIA#1458): asserts that /usr/local/bin/npm and /usr/local/bin/node are not in the baseline npm_registry binaries list to prevent reintroduction of agent npm egress Per Copilot review on NVIDIA#1700. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
c5cdb39 to
429ae49
Compare
…NVIDIA#2180) After a fresh `nemoclaw onboard` with Balanced tier defaults, where the user explicitly skipped messaging channels in step [5/8] and did not tick Discord in step [8/8], `nemoclaw <name> policy-list` reports: ● discord — Discord API, gateway, and CDN access (active on gateway, missing from local state) The sandbox can reach `discord.com`, `gateway.discord.gg`, and `cdn.discordapp.com` without the user having opted in — the base sandbox policy's own header says "deny by default, allow only what's needed for core functionality," which messaging to third-party IM platforms is not. Same story for `api.telegram.org`. This is a regression, not a new bug: - NVIDIA#1705 (2026-04-09, 77051cc) removed pre-allowed `telegram` and `discord` from `nemoclaw-blueprint/policies/openclaw-sandbox.yaml` for exactly this reason. - NVIDIA#1700 (2026-04-14, 855924f), an unrelated npm_registry PR, was rebased on a branch that predated NVIDIA#1705 and re-added both entries during conflict resolution. The CodeRabbit release notes on NVIDIA#1700 even called this out as "Added network policy entries to enable controlled Telegram and Discord messaging access" — it landed along with the legitimate npm_registry tightening and has been in the baseline since. Once a key like `discord` exists in the gateway's loaded policy, `policies.getGatewayPresets()` detects the Discord preset as active (it matches on key presence), and `policy-list` then renders the misleading "active on gateway, missing from local state" line. - Re-remove `telegram` and `discord` entries from `nemoclaw-blueprint/policies/openclaw-sandbox.yaml`. Messaging endpoints are only reachable if the user selects the matching channel in step [5/8] and the corresponding preset is applied on top of the baseline in step [8/8]. Leave a comment block at the removed location referencing NVIDIA#1705, NVIDIA#2180, and the preset path so the next merge-conflict resolution does not casually re-add them. - Add three regression tests in `test/validate-blueprint.test.ts` mirroring the existing `NVIDIA#1583` GitHub pattern: - `regression NVIDIA#2180: base policy does not silently grant Telegram access` - `regression NVIDIA#2180: base policy does not silently grant Discord access` - `regression NVIDIA#2180: base policy does not silently grant Slack access` (guard against the same merge pattern re-adding Slack even though it was never in the baseline historically) Each asserts both the key absence in `network_policies` and the absence of any host-matching endpoint anywhere in the base policy, so a rename can't smuggle the grant back in. - `npx vitest run test/validate-blueprint.test.ts test/policies.test.ts` — 124 tests pass including the 3 new regressions. - `npx vitest run test/validate-configs-dangerous-hosts.test.ts test/onboard.test.ts` — 160 tests pass, no onboard flow regressions. Touches only the base policy YAML and the blueprint validator. Does not modify any preset (presets/telegram.yaml, presets/discord.yaml, presets/slack.yaml) — users who enabled messaging via onboard still get the same preset applied on top of baseline and retain the same endpoint access. The permissive variant (openclaw-sandbox-permissive.yaml), used for `--dangerously-skip-permissions`, is intentionally unchanged. Fixes NVIDIA#2180. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
…NVIDIA#2180) After a fresh `nemoclaw onboard` with Balanced tier defaults, where the user explicitly skipped messaging channels in step [5/8] and did not tick Discord in step [8/8], `nemoclaw <name> policy-list` reports: ● discord — Discord API, gateway, and CDN access (active on gateway, missing from local state) The sandbox can reach `discord.com`, `gateway.discord.gg`, and `cdn.discordapp.com` without the user having opted in — the base sandbox policy's own header says "deny by default, allow only what's needed for core functionality," which messaging to third-party IM platforms is not. Same story for `api.telegram.org`. This is a regression, not a new bug: - NVIDIA#1705 (2026-04-09, 77051cc) removed pre-allowed `telegram` and `discord` from `nemoclaw-blueprint/policies/openclaw-sandbox.yaml` for exactly this reason. - NVIDIA#1700 (2026-04-14, 855924f), an unrelated npm_registry PR, was rebased on a branch that predated NVIDIA#1705 and re-added both entries during conflict resolution. The CodeRabbit release notes on NVIDIA#1700 even called this out as "Added network policy entries to enable controlled Telegram and Discord messaging access" — it landed along with the legitimate npm_registry tightening and has been in the baseline since. Once a key like `discord` exists in the gateway's loaded policy, `policies.getGatewayPresets()` detects the Discord preset as active (it matches on key presence), and `policy-list` then renders the misleading "active on gateway, missing from local state" line. - Re-remove `telegram` and `discord` entries from `nemoclaw-blueprint/policies/openclaw-sandbox.yaml`. Messaging endpoints are only reachable if the user selects the matching channel in step [5/8] and the corresponding preset is applied on top of the baseline in step [8/8]. Leave a comment block at the removed location referencing NVIDIA#1705, NVIDIA#2180, and the preset path so the next merge-conflict resolution does not casually re-add them. - Add three regression tests in `test/validate-blueprint.test.ts` mirroring the existing `NVIDIA#1583` GitHub pattern: - `regression NVIDIA#2180: base policy does not silently grant Telegram access` - `regression NVIDIA#2180: base policy does not silently grant Discord access` - `regression NVIDIA#2180: base policy does not silently grant Slack access` (guard against the same merge pattern re-adding Slack even though it was never in the baseline historically) Each asserts both the key absence in `network_policies` and the absence of any host-matching endpoint anywhere in the base policy, so a rename can't smuggle the grant back in. - `npx vitest run test/validate-blueprint.test.ts test/policies.test.ts` — 124 tests pass including the 3 new regressions. - `npx vitest run test/validate-configs-dangerous-hosts.test.ts test/onboard.test.ts` — 160 tests pass, no onboard flow regressions. Touches only the base policy YAML and the blueprint validator. Does not modify any preset (presets/telegram.yaml, presets/discord.yaml, presets/slack.yaml) — users who enabled messaging via onboard still get the same preset applied on top of baseline and retain the same endpoint access. The permissive variant (openclaw-sandbox-permissive.yaml), used for `--dangerously-skip-permissions`, is intentionally unchanged. Fixes NVIDIA#2180. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
…NVIDIA#2180) After a fresh `nemoclaw onboard` with Balanced tier defaults, where the user explicitly skipped messaging channels in step [5/8] and did not tick Discord in step [8/8], `nemoclaw <name> policy-list` reports: ● discord — Discord API, gateway, and CDN access (active on gateway, missing from local state) The sandbox can reach `discord.com`, `gateway.discord.gg`, and `cdn.discordapp.com` without the user having opted in — the base sandbox policy's own header says "deny by default, allow only what's needed for core functionality," which messaging to third-party IM platforms is not. Same story for `api.telegram.org`. This is a regression, not a new bug: - NVIDIA#1705 (2026-04-09, 77051cc) removed pre-allowed `telegram` and `discord` from `nemoclaw-blueprint/policies/openclaw-sandbox.yaml` for exactly this reason. - NVIDIA#1700 (2026-04-14, 855924f), an unrelated npm_registry PR, was rebased on a branch that predated NVIDIA#1705 and re-added both entries during conflict resolution. The CodeRabbit release notes on NVIDIA#1700 even called this out as "Added network policy entries to enable controlled Telegram and Discord messaging access" — it landed along with the legitimate npm_registry tightening and has been in the baseline since. Once a key like `discord` exists in the gateway's loaded policy, `policies.getGatewayPresets()` detects the Discord preset as active (it matches on key presence), and `policy-list` then renders the misleading "active on gateway, missing from local state" line. - Re-remove `telegram` and `discord` entries from `nemoclaw-blueprint/policies/openclaw-sandbox.yaml`. Messaging endpoints are only reachable if the user selects the matching channel in step [5/8] and the corresponding preset is applied on top of the baseline in step [8/8]. Leave a comment block at the removed location referencing NVIDIA#1705, NVIDIA#2180, and the preset path so the next merge-conflict resolution does not casually re-add them. - Add three regression tests in `test/validate-blueprint.test.ts` mirroring the existing `NVIDIA#1583` GitHub pattern: - `regression NVIDIA#2180: base policy does not silently grant Telegram access` - `regression NVIDIA#2180: base policy does not silently grant Discord access` - `regression NVIDIA#2180: base policy does not silently grant Slack access` (guard against the same merge pattern re-adding Slack even though it was never in the baseline historically) Each asserts both the key absence in `network_policies` and the absence of any host-matching endpoint anywhere in the base policy, so a rename can't smuggle the grant back in. - `npx vitest run test/validate-blueprint.test.ts test/policies.test.ts` — 124 tests pass including the 3 new regressions. - `npx vitest run test/validate-configs-dangerous-hosts.test.ts test/onboard.test.ts` — 160 tests pass, no onboard flow regressions. Touches only the base policy YAML and the blueprint validator. Does not modify any preset (presets/telegram.yaml, presets/discord.yaml, presets/slack.yaml) — users who enabled messaging via onboard still get the same preset applied on top of baseline and retain the same endpoint access. The permissive variant (openclaw-sandbox-permissive.yaml), used for `--dangerously-skip-permissions`, is intentionally unchanged. Fixes NVIDIA#2180. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
## Summary The base sandbox policy (`nemoclaw-blueprint/policies/openclaw-sandbox.yaml`) was silently granting every sandbox egress to `api.telegram.org`, `discord.com`, `gateway.discord.gg`, and `cdn.discordapp.com` — regardless of whether the user enabled the telegram/discord messaging channel in step [5/8] or ticked the preset in step [8/8] of onboard. This is a regression of a previously-fixed behavior. After a fresh onboard that explicitly skipped messaging channels and did not tick Discord in the Balanced-tier preset picker, `nemoclaw <name> policy-list` reports: ``` ● discord — Discord API, gateway, and CDN access (active on gateway, missing from local state) ``` ## Problem Regression history: - [#1705](#1705) (2026-04-09, [`77051cc8`](77051cc8)) — removed `telegram` and `discord` from baseline "for exactly this reason." Explicitly called it a data exfiltration vector. - [#1700](#1700) (2026-04-14, [`855924fd`](855924fd)) — an unrelated npm_registry PR that was rebased on a branch predating #1705. The CodeRabbit release notes on #1700 even flagged it: *"Added network policy entries to enable controlled Telegram and Discord messaging access."* The messaging entries came back as part of that PR's conflict-resolution and have been in the baseline since. Once `discord` exists as a key in the gateway's loaded policy, `policies.getGatewayPresets()` detects the Discord preset as active (it matches on key presence). `nemoclaw policy-list` then renders the misleading "active on gateway, missing from local state" line for a preset the user never selected — and the egress is actually enforced, so it's a real capability grant, not just a display bug. ## Test plan - [x] `npx vitest run test/validate-blueprint.test.ts test/policies.test.ts` — 124 tests pass, including the three new regression tests that guard against this specific re-add pattern for telegram, discord, and slack. - [x] `npx vitest run test/validate-configs-dangerous-hosts.test.ts test/onboard.test.ts` — 160 tests pass. No onboard-flow regressions. - [x] Manually verified that users who enable a messaging channel in step [5/8] and apply the corresponding preset in step [8/8] still get identical endpoint access via `presets/{telegram,discord}.yaml` (no preset YAML changes in this PR). - [x] `openclaw-sandbox-permissive.yaml` (used for `--dangerously-skip-permissions`) unchanged — permissive users still get pre-allowed messaging as before. Fixes #2180. Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Removed default network permissions for Telegram and Discord from the sandbox baseline; messaging endpoints (Telegram, Discord, Slack) are no longer enabled by default and must be added via opt-in presets during onboarding. * **Tests** * Added regression tests to ensure messaging provider access (Telegram, Discord, Slack) remains restricted in the baseline policy and cannot be reintroduced inadvertently. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com> Co-authored-by: latenighthackathon <latenighthackathon@users.noreply.github.com> Co-authored-by: J. Yaunches <jyaunches@nvidia.com>
Problem
With 'none' policy selected during onboard,
npm installstill succeeded because the baseline policy (openclaw-sandbox.yaml) included/usr/local/bin/npmand/usr/local/bin/nodein thenpm_registrybinaries list. This bypassed the user's intent of no external network access.The baseline
npm_registryentry exists solely foropenclaw plugins install— not for agent-driven npm usage. Any sandbox with 'none' preset should block npm from the agent.Fix
Removed
/usr/local/bin/npmand/usr/local/bin/nodefrom the baselinenpm_registrybinaries list. Only/usr/local/bin/openclawretains access toregistry.npmjs.orgby default.Users who need npm/node network access in the sandbox should add the
npmpreset during onboard or afterwards vianemoclaw policy.Testing
nemoclaw onboardwith no policy presets →npm installshould now be blocked (403 Forbidden from proxy)openclaw plugins install <plugin>should still work (uses the openclaw binary)nemoclaw onboardwith npm preset →npm installstill works as expectedFixes #1458
Signed-off-by: Benedikt Schackenberg 6381261+BenediktSchackenberg@users.noreply.github.com
Summary by CodeRabbit