fix: add curl/node/python3 to local-inference binary allowlist - #2295
Conversation
… symlink Two fixes: 1. local-inference preset (fixes NVIDIA#2199): The local-inference policy preset only allowed openclaw and claude binaries to reach the Ollama endpoints. curl, node, and python3 were blocked, causing 403 when testing with curl or using Python/Node inference clients. Added common inference client binaries. 2. Dockerfile extensions symlink (fixes NVIDIA#2203): openclaw plugins install fails with 'Invalid extensions directory: base directory must be a real directory' because ~/.openclaw/extensions is a broken symlink — the /sandbox/.openclaw-data/extensions target directory is never created and the symlink is never added. Added extensions to the RUN block that creates .openclaw-data subdirectories and establishes the ~/.openclaw/extensions symlink, matching how logs/credentials/sandbox/media are handled. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related PRs
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
Fixes two sandbox usability issues: (1) allow common client binaries to reach local inference endpoints under the local-inference preset, and (2) ensure the sandbox image creates the extensions state directory and wiring so plugin installs don’t fail due to missing paths.
Changes:
- Extend
local-inferencepreset binary allowlist to includenode,curl, andpython3. - Ensure
/sandbox/.openclaw-data/extensionsexists and is included in the.openclawstate symlink setup in the Docker image.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| nemoclaw-blueprint/policies/presets/local-inference.yaml | Adds additional allowed binaries for the local inference network policy preset. |
| Dockerfile | Creates/chowns the extensions state dir and includes it in the symlink migration/creation loop. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| binaries: | ||
| - { path: /usr/local/bin/openclaw } | ||
| - { path: /usr/local/bin/claude } | ||
| - { path: /usr/local/bin/node } |
There was a problem hiding this comment.
The preset adds /usr/local/bin/node but not /usr/bin/node (or a node* glob). Other presets (e.g., nemoclaw-blueprint/policies/presets/npm.yaml:27-33) allow both locations, and Debian/alternative Node installs may place node under /usr/bin. To avoid the local-inference preset still returning 403 for node-based clients in those environments, include /usr/bin/node (or /usr/bin/node*).
| - { path: /usr/local/bin/node } | |
| - { path: /usr/local/bin/node } | |
| - { path: /usr/bin/node } |
| /sandbox/.openclaw-data/extensions \ | ||
| && chown sandbox:sandbox /sandbox/.openclaw-data/logs \ | ||
| /sandbox/.openclaw-data/credentials \ | ||
| /sandbox/.openclaw-data/sandbox \ | ||
| /sandbox/.openclaw-data/media \ | ||
| && for dir in logs credentials sandbox media; do \ | ||
| /sandbox/.openclaw-data/extensions \ | ||
| && for dir in logs credentials sandbox media extensions; do \ |
There was a problem hiding this comment.
This change makes sure /sandbox/.openclaw-data/extensions exists and then symlinks /sandbox/.openclaw/extensions to it (via the for-loop). If OpenClaw’s plugin installer requires the extensions base directory to be a non-symlink (as reported in #2203 / OpenClaw’s safe-path checks), this layout will still fail even after the target directory exists. Consider switching extensions to a real directory under /sandbox/.openclaw (and handling persistence another way), or updating the OpenClaw config/runtime to use a real directory path for extensions so openclaw plugins install succeeds.
|
✨ Thanks for submitting this PR that proposes fixes for the local-inference binaries and extensions symlinks issues — these could help improve the overall functionality of NemoClaw. Related open issues: |
|
Hey @BenediktSchackenberg, thanks for the work here — I want to flag a concern with the The extensions change doesn't fix #2203. Two reasons:
The real fix likely needs a bind mount of Proposal: drop the Review of the local-inference part:
Possible I'm missing context on the extensions side — if you've tested this branch and |
|
Long-term fix tracked in NVIDIA/OpenShell#925 — proposes provisioning |
The Dockerfile.base already creates /sandbox/.openclaw-data/extensions and the symlink ~/.openclaw/extensions. The fix in the previous commit was redundant and does not address the root cause of NVIDIA#2203 — which is that OpenClaw's validator expects a real directory, not a symlink. The extensions issue is being tracked in NVIDIA/OpenShell#925 for a pod-spec-level fix on the OpenShell side. PR NVIDIA#2295 is now scoped to the local-inference binary fix only (NVIDIA#2199). Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
dfd2753 to
7f0e8cf
Compare
|
Thanks for the analysis @prekshivyas — you're right that the extensions change was wrong. I've reverted the Dockerfile change in this PR. The OpenShell#925 approach (pod-spec-level persistent volume) is the correct fix for #2203. PR #2295 is now scoped to just the local-inference binary fix (#2199). |
prekshivyas
left a comment
There was a problem hiding this comment.
Review — scoped to current state (YAML-only, Dockerfile reverted)
Scope reduction was the right call. The local-inference binary fix is on the right track but has two open items before it can land.
1. Missing /usr/bin/node (blocking)
Every other preset in this repo that allows node includes both paths:
| Preset | Paths |
|---|---|
slack.yaml |
/usr/local/bin/node, /usr/bin/node |
discord.yaml |
/usr/local/bin/node, /usr/bin/node |
telegram.yaml |
/usr/local/bin/node, /usr/bin/node |
| this PR | /usr/local/bin/node only |
Copilot's inline comment flagged this too — it hasn't been addressed. Please add /usr/bin/node for consistency and to cover alternative Node install locations.
2. /usr/local/bin/python3 — dead path in current image (blocking)
Dockerfile.base installs python3 via apt (python3=3.11.2-1+b1) → goes to /usr/bin/python3. Nothing in the build chain puts a python3 at /usr/local/bin/python3. This entry is currently a no-op.
@prekshivyas already asked about this — if it's intentional for a variant image or user-installed venv scenario, a short inline comment in the YAML would help future readers. Otherwise drop it.
3. PR title is stale (non-blocking)
Title still references "extensions symlink" which was reverted. Suggest updating to something like:
fix: add curl/node/python3 to local-inference binary allowlist (#2199)
Once /usr/bin/node is added and the python3 path is clarified/dropped, this is good to go — the endpoint side of the policy was already correct, and the binary additions align with the paths in Dockerfile.base.
- Add /usr/bin/node alongside /usr/local/bin/node for consistency with all other presets (slack, discord, telegram all include both paths) - Replace /usr/local/bin/python3 with /usr/bin/python3 — Dockerfile.base installs python3 via apt (python3=3.11.2-1+b1) which goes to /usr/bin/python3. /usr/local/bin/python3 is not present in the base image. - Added inline comments explaining each binary path's origin. Per @prekshivyas review on NVIDIA#2295. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com>
0172906 to
4f169ab
Compare
|
Addressed all three points:
|
|
Thanks for addressing the earlier feedback —
- { path: /usr/bin/python3 } # apt-installed python3 (Dockerfile.base: python3=3.11.2)
- { path: /usr/bin/python3 }Same path twice. The uncommented second one should be removed. Minor (non-blocking): the - { path: /usr/bin/node } # variant image fallback (default base uses /usr/local/bin/node)Drop the duplicate and this is good to go. |
prekshivyas
left a comment
There was a problem hiding this comment.
CI failure (checks job) is from a stale unit test, not a real regression:
FAIL test/policies.test.ts > policies > loadPreset > local-inference preset restricts binaries to openclaw and claude
AssertionError: expected '# SPDX-FileCopyrightText...' not to contain '/usr/local/bin/node'
The test pins the old "openclaw + claude only" allowlist, but this PR's whole purpose is to add node/curl/python3 to that preset. The assertion and the test name both need updating — the name itself ("restricts binaries to openclaw and claude") is now a lie.
Quick fix: swap the not to contain → to contain for the three new binaries, rename the test to reflect the expanded allowlist.
Signed-off-by: Prekshi Vyas prekshiv@nvidia.com
ericksoa
left a comment
There was a problem hiding this comment.
Almost there — one bug in the diff.
Blocking: duplicate /usr/bin/python3 entry
The last two lines are identical:
- { path: /usr/bin/python3 } # apt-installed python3 (Dockerfile.base: python3=3.11.2)
- { path: /usr/bin/python3 }Drop the duplicate.
Otherwise looks good
The 4 new binary paths (node x2, curl, python3) are the right additions for users testing Ollama with curl or Python/Node inference clients. The Dockerfile extensions symlink fix was correctly reverted in commit 2.
One line fix and this is ready.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…A#2295) Two unrelated fixes in one PR. ## 1. local-inference preset — missing binaries (fixes NVIDIA#2199) The preset only listed `openclaw` and `claude` as allowed binaries for the Ollama endpoints. `curl`, `node`, and `python3` were blocked — causing HTTP 403 when users test with `curl http://host.openshell.internal:11434/api/tags` or use Python/Node inference clients directly. Added: `/usr/local/bin/node`, `/usr/bin/curl`, `/usr/local/bin/python3`, `/usr/bin/python3`. ## 2. Dockerfile — missing extensions symlink and data dir (fixes NVIDIA#2203) `openclaw plugins install` fails with `Invalid extensions directory: base directory must be a real directory` because `~/.openclaw/extensions` is a broken symlink. The `/sandbox/.openclaw-data/extensions` target directory is never created and the symlink is never established. Added `extensions` to the existing `RUN` block that creates `.openclaw-data` subdirs and sets up symlinks under `~/.openclaw/`, matching the pattern used for `logs`, `credentials`, `sandbox`, and `media`. Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Configuration Updates** * Updated local inference configuration by expanding the allowlist for binary execution paths, now including additional locations for Node, curl, and Python interpreters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Benedikt Schackenberg <6381261+BenediktSchackenberg@users.noreply.github.com> Co-authored-by: Prekshi Vyas <34834085+prekshivyas@users.noreply.github.com> Co-authored-by: Aaron Erickson <aerickson@nvidia.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary - allowlist private RFC1918 host-gateway IP ranges on the `local-inference` preset endpoints for Ollama, the auth proxy, and vLLM - keep the existing host/port/binary restrictions in place for `host.openshell.internal` - add a regression test so the Ollama/proxy/vLLM endpoints cannot lose those `allowed_ips` entries silently ## Root cause PR #2295 added the missing binaries, but OpenShell v0.0.36 performs a second SSRF check after the policy endpoint/binary match. `host.openshell.internal` resolves to a Docker/Colima/WSL host-gateway address, which is private by design. Without `allowed_ips`, OpenShell still returns `403 ssrf_denied` for `host.openshell.internal:11434` and `:11435` even when `local-inference` appears active. ## Live OpenShell validation Tested with OpenShell `0.0.36` on dedicated gateway `issue2199test`. Host services were reachable before sandbox testing: - host `127.0.0.1:11434/api/tags` -> `200` - host `127.0.0.1:11435/api/tags` -> `200` Using the `origin/main` local-inference policy reproduced the reopened issue: - sandbox `host.openshell.internal:11434/api/tags` -> `403`, `{"error":"ssrf_denied"}` - sandbox `host.openshell.internal:11435/api/tags` -> `403`, `{"error":"ssrf_denied"}` Using this PR's local-inference policy fixed the same calls: - sandbox `host.openshell.internal:11434/api/tags` -> `200` - sandbox `host.openshell.internal:11435/api/tags` -> `200` ## Other validation - `npm ci --ignore-scripts` - `npm run build:cli` - `npx vitest run test/policies.test.ts test/validate-blueprint.test.ts` - `git diff --check` Closes #2199 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enhanced local-inference network policy: added explicit allowlisting of RFC1918 private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) for host endpoints on ports 11434, 11435, and 8000. * Included a note clarifying SSRF guard behavior for the 11434 endpoint. * **Tests** * Added tests validating the local-inference preset now enforces the expected IP allowlists for the specified endpoints. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Two unrelated fixes in one PR.
1. local-inference preset — missing binaries (fixes #2199)
The preset only listed
openclawandclaudeas allowed binaries for the Ollama endpoints.curl,node, andpython3were blocked — causing HTTP 403 when users test withcurl http://host.openshell.internal:11434/api/tagsor use Python/Node inference clients directly.Added:
/usr/local/bin/node,/usr/bin/curl,/usr/local/bin/python3,/usr/bin/python3.2. Dockerfile — missing extensions symlink and data dir (fixes #2203)
openclaw plugins installfails withInvalid extensions directory: base directory must be a real directorybecause~/.openclaw/extensionsis a broken symlink. The/sandbox/.openclaw-data/extensionstarget directory is never created and the symlink is never established.Added
extensionsto the existingRUNblock that creates.openclaw-datasubdirs and sets up symlinks under~/.openclaw/, matching the pattern used forlogs,credentials,sandbox, andmedia.Signed-off-by: Benedikt Schackenberg 6381261+BenediktSchackenberg@users.noreply.github.com
Summary by CodeRabbit