diff --git a/.agents/skills/nemoclaw-user-reference/references/network-policies.md b/.agents/skills/nemoclaw-user-reference/references/network-policies.md index 947a468ecff..5d0d8d095ea 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 92a45115fbb..a6b97c54ef5 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/nemoclaw-blueprint/policies/openclaw-sandbox.yaml b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml index e1e87eb7b46..85f342be0e2 100644 --- a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml +++ b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml @@ -196,8 +196,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: @@ -210,5 +212,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 } 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", () => {