From 6ac2667eb5067e680b0951c6f7a1c59b561294e7 Mon Sep 17 00:00:00 2001 From: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com> Date: Thu, 9 Apr 2026 18:04:14 +0000 Subject: [PATCH 1/2] fix(policy): restrict baseline npm_registry to openclaw binary only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 #1458 Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com> --- .../policies/openclaw-sandbox.yaml | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml index 2ed1cd353de..505d2e1b57f 100644 --- a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml +++ b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml @@ -185,8 +185,10 @@ network_policies: binaries: - { path: /usr/local/bin/openclaw } - # npm registry — needed for `openclaw plugins install` and `npm install`. - # Read-only: agents only fetch packages, never publish. + # 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 endpoints: @@ -199,5 +201,49 @@ network_policies: - allow: { method: GET, path: "/**" } binaries: - { path: /usr/local/bin/openclaw } - - { path: /usr/local/bin/npm } + + # ── Messaging — pre-allowed for OpenClaw agent notifications ──── + # Restricted to node processes to prevent arbitrary data exfiltration + # via curl, wget, python, etc. (See: #272) + telegram: + name: telegram + endpoints: + - host: api.telegram.org + port: 443 + protocol: rest + enforcement: enforce + tls: terminate + rules: + - allow: { method: GET, path: "/bot*/**" } + - allow: { method: POST, path: "/bot*/**" } + - allow: { method: GET, path: "/file/bot*/**" } + binaries: + - { path: /usr/local/bin/node } + + discord: + name: discord + endpoints: + - host: discord.com + port: 443 + protocol: rest + enforcement: enforce + tls: terminate + rules: + - allow: { method: GET, path: "/**" } + - allow: { method: POST, path: "/**" } + # WebSocket gateway — must use access: full (CONNECT tunnel) instead + # of protocol: rest. The proxy's HTTP idle timeout (~2 min) kills + # long-lived WebSocket connections; a CONNECT tunnel avoids + # HTTP-level timeouts entirely. Matches presets/discord.yaml. See #409. + - host: gateway.discord.gg + port: 443 + access: full + - host: cdn.discordapp.com + port: 443 + protocol: rest + enforcement: enforce + tls: terminate + rules: + - allow: { method: GET, path: "/**" } + binaries: - { path: /usr/local/bin/node } From 429ae49ed2078b7f73593b21268a339374055529 Mon Sep 17 00:00:00 2001 From: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com> Date: Thu, 9 Apr 2026 18:27:44 +0000 Subject: [PATCH 2/2] fix(policy): update docs and add regression test for npm_registry fix - 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 (#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 #1700. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com> --- .../references/network-policies.md | 2 +- docs/reference/network-policies.md | 2 +- test/validate-blueprint.test.ts | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.agents/skills/nemoclaw-user-reference/references/network-policies.md b/.agents/skills/nemoclaw-user-reference/references/network-policies.md index 2a1ed77021f..cbf4543c712 100644 --- a/.agents/skills/nemoclaw-user-reference/references/network-policies.md +++ b/.agents/skills/nemoclaw-user-reference/references/network-policies.md @@ -60,7 +60,7 @@ The following endpoint groups are allowed by default: * - `npm_registry` - `registry.npmjs.org:443` - - `/usr/local/bin/openclaw`, `/usr/local/bin/npm`, `/usr/local/bin/node` + - `/usr/local/bin/openclaw` only (openclaw plugins install) - GET only ::: diff --git a/docs/reference/network-policies.md b/docs/reference/network-policies.md index fc8864ccb54..47f9f167d38 100644 --- a/docs/reference/network-policies.md +++ b/docs/reference/network-policies.md @@ -80,7 +80,7 @@ The following endpoint groups are allowed by default: * - `npm_registry` - `registry.npmjs.org:443` - - `/usr/local/bin/openclaw`, `/usr/local/bin/npm`, `/usr/local/bin/node` + - `/usr/local/bin/openclaw` only (openclaw plugins install) - GET only ::: diff --git a/test/validate-blueprint.test.ts b/test/validate-blueprint.test.ts index 7fe9a4cccbc..4034568bae2 100644 --- a/test/validate-blueprint.test.ts +++ b/test/validate-blueprint.test.ts @@ -253,6 +253,19 @@ describe("base sandbox policy", () => { ); expect(githubHosts).toEqual([]); }); + + it("regression #1458: baseline npm_registry must not include npm or node binaries", () => { + const np = policy.network_policies as Record>; + const npmRegistry = np.npm_registry; + expect(npmRegistry).toBeDefined(); + const binaries = npmRegistry.binaries as Array<{ path: string }> | undefined; + expect(Array.isArray(binaries)).toBe(true); + const paths = (binaries ?? []).map((b) => b.path).sort(); + // Only openclaw CLI should reach the npm registry by default. + // npm/node being in this list lets the agent bypass 'none' policy preset. + // Exact allowlist — adding any binary here requires a deliberate review. + expect(paths).toEqual(["/usr/local/bin/openclaw"]); + }); }); describe("github preset", () => {