From 9d0b6592cf15d36579109fe5ecbcf5208757e881 Mon Sep 17 00:00:00 2001 From: Ross Shulyha Date: Sun, 22 Mar 2026 20:50:45 -0400 Subject: [PATCH 1/2] fix: add missing binaries to all policy presets and default telegram/discord policies All 9 presets and the default telegram/discord entries in openclaw-sandbox.yaml lacked binaries sections, causing OpenShell's OPA rego to deny every request with 403 regardless of endpoint match. - Add binaries to all presets (discord, docker, huggingface, jira, npm, outlook, pypi, slack, telegram) - Add binaries to default telegram and discord policies - Switch pypi/npm from tls:terminate to access:full for CONNECT tunneling compatibility - Add test ensuring every preset includes a binaries section Closes #676 Related: #19, #356, #585 Co-Authored-By: Claude Opus 4.6 --- .../policies/openclaw-sandbox.yaml | 14 +++++++++++++ .../policies/presets/discord.yaml | 7 +++++++ .../policies/presets/docker.yaml | 9 ++++++++ .../policies/presets/huggingface.yaml | 10 +++++++++ nemoclaw-blueprint/policies/presets/jira.yaml | 7 +++++++ nemoclaw-blueprint/policies/presets/npm.yaml | 21 ++++++++++--------- .../policies/presets/outlook.yaml | 7 +++++++ nemoclaw-blueprint/policies/presets/pypi.yaml | 20 +++++++++--------- .../policies/presets/slack.yaml | 7 +++++++ .../policies/presets/telegram.yaml | 7 +++++++ test/policies.test.js | 10 +++++++++ 11 files changed, 99 insertions(+), 20 deletions(-) diff --git a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml index 3e3d1cd92..9883376a3 100644 --- a/nemoclaw-blueprint/policies/openclaw-sandbox.yaml +++ b/nemoclaw-blueprint/policies/openclaw-sandbox.yaml @@ -171,6 +171,13 @@ network_policies: rules: - allow: { method: GET, path: "/bot*/**" } - allow: { method: POST, path: "/bot*/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } discord: name: discord @@ -198,3 +205,10 @@ network_policies: tls: terminate rules: - allow: { method: GET, path: "/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/nemoclaw-blueprint/policies/presets/discord.yaml b/nemoclaw-blueprint/policies/presets/discord.yaml index dbbf823de..7be047f56 100644 --- a/nemoclaw-blueprint/policies/presets/discord.yaml +++ b/nemoclaw-blueprint/policies/presets/discord.yaml @@ -32,3 +32,10 @@ network_policies: tls: terminate rules: - allow: { method: GET, path: "/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/nemoclaw-blueprint/policies/presets/docker.yaml b/nemoclaw-blueprint/policies/presets/docker.yaml index 15cbf2fa0..e0277ef0e 100644 --- a/nemoclaw-blueprint/policies/presets/docker.yaml +++ b/nemoclaw-blueprint/policies/presets/docker.yaml @@ -41,3 +41,12 @@ network_policies: rules: - allow: { method: GET, path: "/**" } - allow: { method: POST, path: "/**" } + binaries: + - { path: /usr/bin/docker* } + - { path: /usr/local/bin/docker* } + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/nemoclaw-blueprint/policies/presets/huggingface.yaml b/nemoclaw-blueprint/policies/presets/huggingface.yaml index aa6b653af..db473d601 100644 --- a/nemoclaw-blueprint/policies/presets/huggingface.yaml +++ b/nemoclaw-blueprint/policies/presets/huggingface.yaml @@ -32,3 +32,13 @@ network_policies: rules: - allow: { method: GET, path: "/**" } - allow: { method: POST, path: "/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/local/bin/huggingface-cli } + - { path: /usr/bin/curl } + - { path: /usr/bin/git } + - { path: /usr/bin/git-remote-http* } diff --git a/nemoclaw-blueprint/policies/presets/jira.yaml b/nemoclaw-blueprint/policies/presets/jira.yaml index 04d733d88..79292b127 100644 --- a/nemoclaw-blueprint/policies/presets/jira.yaml +++ b/nemoclaw-blueprint/policies/presets/jira.yaml @@ -33,3 +33,10 @@ network_policies: rules: - allow: { method: GET, path: "/**" } - allow: { method: POST, path: "/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/nemoclaw-blueprint/policies/presets/npm.yaml b/nemoclaw-blueprint/policies/presets/npm.yaml index 75ff4cc95..f5e231d90 100644 --- a/nemoclaw-blueprint/policies/presets/npm.yaml +++ b/nemoclaw-blueprint/policies/presets/npm.yaml @@ -11,15 +11,16 @@ network_policies: endpoints: - host: registry.npmjs.org port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } + access: full - host: registry.yarnpkg.com port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } + access: full + binaries: + - { path: /usr/local/bin/npm* } + - { path: /usr/local/bin/npx* } + - { path: /usr/local/bin/node* } + - { path: /usr/local/bin/yarn* } + - { path: /usr/bin/npm* } + - { path: /usr/bin/npx* } + - { path: /usr/bin/node* } + - { path: /usr/bin/yarn* } diff --git a/nemoclaw-blueprint/policies/presets/outlook.yaml b/nemoclaw-blueprint/policies/presets/outlook.yaml index dafbb5669..0d2e4419f 100644 --- a/nemoclaw-blueprint/policies/presets/outlook.yaml +++ b/nemoclaw-blueprint/policies/presets/outlook.yaml @@ -41,3 +41,10 @@ network_policies: rules: - allow: { method: GET, path: "/**" } - allow: { method: POST, path: "/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/nemoclaw-blueprint/policies/presets/pypi.yaml b/nemoclaw-blueprint/policies/presets/pypi.yaml index f9cde894a..91d3a02a6 100644 --- a/nemoclaw-blueprint/policies/presets/pypi.yaml +++ b/nemoclaw-blueprint/policies/presets/pypi.yaml @@ -11,15 +11,15 @@ network_policies: endpoints: - host: pypi.org port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } + access: full - host: files.pythonhosted.org port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } + access: full + binaries: + - { path: /usr/bin/python3* } + - { path: /usr/bin/pip* } + - { path: /usr/local/bin/python3* } + - { path: /usr/local/bin/pip* } + - { path: /sandbox/.venv/bin/python* } + - { path: /sandbox/.venv/bin/pip* } + - { path: /sandbox/.local/bin/pip* } diff --git a/nemoclaw-blueprint/policies/presets/slack.yaml b/nemoclaw-blueprint/policies/presets/slack.yaml index b31134268..37f40bed8 100644 --- a/nemoclaw-blueprint/policies/presets/slack.yaml +++ b/nemoclaw-blueprint/policies/presets/slack.yaml @@ -33,3 +33,10 @@ network_policies: rules: - allow: { method: GET, path: "/**" } - allow: { method: POST, path: "/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/nemoclaw-blueprint/policies/presets/telegram.yaml b/nemoclaw-blueprint/policies/presets/telegram.yaml index 2e0e4f776..af7a3befd 100644 --- a/nemoclaw-blueprint/policies/presets/telegram.yaml +++ b/nemoclaw-blueprint/policies/presets/telegram.yaml @@ -17,3 +17,10 @@ network_policies: rules: - allow: { method: GET, path: "/bot*/**" } - allow: { method: POST, path: "/bot*/**" } + binaries: + - { path: /usr/local/bin/openclaw } + - { path: /usr/local/bin/node* } + - { path: /usr/bin/node* } + - { path: /usr/bin/python3* } + - { path: /usr/local/bin/python3* } + - { path: /usr/bin/curl } diff --git a/test/policies.test.js b/test/policies.test.js index 51747a7a4..cc77afb19 100644 --- a/test/policies.test.js +++ b/test/policies.test.js @@ -119,5 +119,15 @@ describe("policies", () => { expect(content.includes("network_policies:")).toBeTruthy(); } }); + + it("every preset includes a binaries section", () => { + // Without binaries, the OPA rego policy in OpenShell's proxy can't + // match traffic to the network policy and returns 403 Forbidden. + // See: https://github.com/NVIDIA/NemoClaw/issues/19 + for (const p of policies.listPresets()) { + const content = policies.loadPreset(p.name); + expect(content.includes("binaries:")).toBeTruthy(); + } + }); }); }); From 58fe8a9efab8de2af71d8784c1e6a1a13a109aff Mon Sep 17 00:00:00 2001 From: Ross Shulyha Date: Sun, 22 Mar 2026 20:58:55 -0400 Subject: [PATCH 2/2] fix: switch docker preset to access: full for CONNECT tunneling Docker pull/push operations use CONNECT tunneling through the proxy, which breaks under tls: terminate. Switch to access: full, matching the approach used for pypi and npm presets. Addresses CodeRabbit review feedback. Co-Authored-By: Claude Opus 4.6 --- .../policies/presets/docker.yaml | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/nemoclaw-blueprint/policies/presets/docker.yaml b/nemoclaw-blueprint/policies/presets/docker.yaml index e0277ef0e..1dbad45ed 100644 --- a/nemoclaw-blueprint/policies/presets/docker.yaml +++ b/nemoclaw-blueprint/policies/presets/docker.yaml @@ -11,36 +11,16 @@ network_policies: endpoints: - host: registry-1.docker.io port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } - - allow: { method: POST, path: "/**" } + access: full - host: auth.docker.io port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } - - allow: { method: POST, path: "/**" } + access: full - host: nvcr.io port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } - - allow: { method: POST, path: "/**" } + access: full - host: authn.nvidia.com port: 443 - protocol: rest - enforcement: enforce - tls: terminate - rules: - - allow: { method: GET, path: "/**" } - - allow: { method: POST, path: "/**" } + access: full binaries: - { path: /usr/bin/docker* } - { path: /usr/local/bin/docker* }