Skip to content

Commit f89cc63

Browse files
committed
chore: use uv for Python management, consolidate Dockerfile layers, and clean up policies
- Remove deadsnakes PPA, apt Python packages, and pip bootstrap; let uv manage the full Python 3.13 toolchain - Merge Node.js install + npm upgrade into a single RUN layer - Merge all npm global installs (vuln fixes + CLI tools) into one call - Add uv cache clean after python install and venv creation - Copy base policy.yaml into the image instead of just creating the dir - Remove duplicate UV_PYTHON_INSTALL_DIR ENV and redundant mkdir - Update syntax directive from dockerfile:1.4 to dockerfile:1 - Revert nemoclaw/openclaw policies to main and replace repo-specific rules (johntmyers/alpha-claw, bravo-claw) with generic placeholders
1 parent 60407cb commit f89cc63

File tree

4 files changed

+258
-208
lines changed

4 files changed

+258
-208
lines changed

sandboxes/base/Dockerfile

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# syntax=docker/dockerfile:1.4
1+
# syntax=docker/dockerfile:1
22

33
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
44
# SPDX-License-Identifier: Apache-2.0
@@ -20,9 +20,9 @@ ENV DEBIAN_FRONTEND=noninteractive \
2020
WORKDIR /sandbox
2121

2222
# Core system dependencies
23-
# python3.13 + pip: agent scripting and SDK usage (deadsnakes PPA for Noble)
2423
# iproute2: network namespace management (ip netns, veth pairs)
2524
# dnsutils: dig, nslookup
25+
# Python is managed entirely by uv (see devtools stage).
2626
RUN apt-get update && apt-get install -y --no-install-recommends \
2727
ca-certificates \
2828
curl \
@@ -33,17 +33,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
3333
netcat-openbsd \
3434
openssh-sftp-server \
3535
procps \
36-
software-properties-common \
3736
traceroute \
38-
&& add-apt-repository -y ppa:deadsnakes/ppa \
39-
&& apt-get update \
40-
&& apt-get install -y --no-install-recommends \
41-
python3.13 \
42-
python3.13-venv \
43-
python3.13-dev \
44-
&& curl -sS https://bootstrap.pypa.io/get-pip.py | python3.13 \
45-
&& update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.13 1 \
46-
&& update-alternatives --install /usr/bin/python python /usr/bin/python3.13 1 \
4737
&& rm -rf /var/lib/apt/lists/*
4838

4939
# Create supervisor and sandbox users/groups
@@ -57,25 +47,32 @@ FROM system AS devtools
5747
# Pin to a specific patch version for reproducible builds.
5848
# CVE-2026-21637, CVE-2025-59466, CVE-2025-59465, CVE-2025-55131 affect
5949
# Node.js <= 22.22.1. Update to 22.23.0+ when a patched release ships.
50+
#
51+
# npm is upgraded to v11 in the same layer to avoid caching the old npm.
52+
# npm 11 ships tar@^7.5.9, fixing tar@6.2.1 vulns bundled in npm 10
53+
# (GHSA-r6q2-hw4h-h46w, GHSA-8qq5-rm4j-mr97, GHSA-83g3-92jg-28cx,
54+
# GHSA-34x7-hfp2-rc4v, GHSA-qffp-2rhf-9h96).
6055
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
6156
apt-get install -y --no-install-recommends \
6257
build-essential \
6358
git \
6459
nodejs=22.22.1-1nodesource1 \
6560
vim-tiny \
6661
nano \
67-
&& rm -rf /var/lib/apt/lists/*
68-
69-
# Upgrade npm to v11 which ships tar@^7.5.9 (fixes tar@6.2.1 vulns bundled in
70-
# npm 10: GHSA-r6q2-hw4h-h46w, GHSA-8qq5-rm4j-mr97, GHSA-83g3-92jg-28cx,
71-
# GHSA-34x7-hfp2-rc4v, GHSA-qffp-2rhf-9h96).
72-
RUN npm install -g npm@11.11.0
73-
74-
# Fix transitive tar and @hono/node-server vulnerabilities
75-
# (GHSA-qffp-2rhf-9h96, GHSA-9ppj-qmqm-q256, GHSA-8qq5-rm4j-mr97,
76-
# GHSA-r6q2-hw4h-h46w, GHSA-34x7-hfp2-rc4v, GHSA-83g3-92jg-28cx,
77-
# GHSA-wc8c-qw6v-h7f6).
78-
RUN npm install -g tar@7.5.11 @hono/node-server@1.19.11
62+
&& rm -rf /var/lib/apt/lists/* \
63+
&& npm install -g npm@11.11.0
64+
65+
# Global npm packages — pinned for reproducibility.
66+
# tar + @hono/node-server: transitive vuln fixes
67+
# (GHSA-qffp-2rhf-9h96, GHSA-9ppj-qmqm-q256, GHSA-8qq5-rm4j-mr97,
68+
# GHSA-r6q2-hw4h-h46w, GHSA-34x7-hfp2-rc4v, GHSA-83g3-92jg-28cx,
69+
# GHSA-wc8c-qw6v-h7f6).
70+
# opencode-ai + @openai/codex: agent CLIs.
71+
RUN npm install -g \
72+
tar@7.5.11 \
73+
@hono/node-server@1.19.11 \
74+
opencode-ai@1.2.18 \
75+
@openai/codex@0.111.0
7976

8077
# GitHub CLI
8178
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
@@ -90,12 +87,14 @@ RUN curl -fsSL https://claude.ai/install.sh | bash \
9087
&& cp /root/.local/bin/claude /usr/local/bin/claude \
9188
&& chmod 755 /usr/local/bin/claude
9289

93-
# Install OpenCode CLI and Codex CLI (OpenAI) with pinned versions for
94-
# reproducible builds.
95-
RUN npm install -g opencode-ai@1.2.18 @openai/codex@0.111.0
96-
97-
# uv (Python package manager) — pinned for reproducibility
90+
# uv (Python package/project manager) — pinned for reproducibility.
91+
# uv manages the Python toolchain; no system Python packages are needed.
9892
COPY --from=ghcr.io/astral-sh/uv:0.10.8 /uv /usr/local/bin/uv
93+
ENV UV_PYTHON_INSTALL_DIR="/sandbox/.uv/python"
94+
RUN uv python install 3.13 && \
95+
ln -s $(uv python find 3.13) /usr/local/bin/python3 && \
96+
ln -s $(uv python find 3.13) /usr/local/bin/python && \
97+
uv cache clean
9998

10099
# Final base image
101100
FROM devtools AS final
@@ -105,11 +104,10 @@ FROM devtools AS final
105104
# VIRTUAL_ENV and UV_PYTHON_INSTALL_DIR are also exported in .bashrc
106105
# so that login shell sessions (interactive and exec) see them.
107106
ENV PATH="/sandbox/.venv/bin:/usr/local/bin:/usr/bin:/bin" \
108-
VIRTUAL_ENV="/sandbox/.venv" \
109-
UV_PYTHON_INSTALL_DIR="/sandbox/.uv/python"
107+
VIRTUAL_ENV="/sandbox/.venv"
110108

111-
# Ensure policy directory exists
112-
RUN mkdir -p /etc/navigator
109+
# Default sandbox network / filesystem policy
110+
COPY policy.yaml /etc/navigator/policy.yaml
113111

114112
# Copy custom skills into the image.
115113
# To add a skill, create a subdirectory under sandboxes/base/skills/
@@ -118,11 +116,12 @@ RUN mkdir -p /etc/navigator
118116
COPY skills/ /sandbox/.agents/skills/
119117

120118
# Set up sandbox user home directory
121-
RUN mkdir -p /sandbox/.agents/skills /sandbox/.claude/skills && \
122-
# Create a writable venv that inherits all system packages.
123-
# Sandbox users can `pip install` or `uv pip install` into
119+
RUN mkdir -p /sandbox/.claude/skills && \
120+
# Create a writable venv using uv-managed Python 3.13.
121+
# Sandbox users can `uv pip install` (or `pip install`) into
124122
# this venv without touching the base image layer.
125-
uv venv --python /usr/bin/python3.13 --seed --system-site-packages /sandbox/.venv && \
123+
uv venv --python 3.13 --seed /sandbox/.venv && \
124+
uv cache clean && \
126125
chown -R sandbox:sandbox /sandbox/.venv && \
127126
# Minimal shell init files so interactive and non-interactive shells
128127
# get a sane PATH and prompt. Without these, bash sources nothing

sandboxes/base/policy.yaml

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
version: 1
5+
6+
# --- Sandbox setup configuration (queried once at startup) ---
7+
8+
filesystem_policy:
9+
include_workdir: true
10+
read_only:
11+
- /usr
12+
- /lib
13+
- /proc
14+
- /dev/urandom
15+
- /app
16+
- /etc
17+
- /var/log
18+
read_write:
19+
- /sandbox
20+
- /tmp
21+
- /dev/null
22+
23+
landlock:
24+
compatibility: best_effort
25+
26+
process:
27+
run_as_user: sandbox
28+
run_as_group: sandbox
29+
30+
# --- Network policies (queried per-CONNECT request) ---
31+
#
32+
# Each named policy maps a set of allowed (binary, endpoint) pairs.
33+
# Binary identity is resolved via /proc/net/tcp inode lookup + /proc/{pid}/exe.
34+
# Ancestors (/proc/{pid}/status PPid walk) and cmdline paths are also matched.
35+
# SHA256 integrity is enforced in Rust via trust-on-first-use, not here.
36+
37+
network_policies:
38+
claude_code:
39+
name: claude-code
40+
endpoints:
41+
- { host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full, tls: terminate }
42+
- { host: statsig.anthropic.com, port: 443 }
43+
- { host: sentry.io, port: 443 }
44+
- { host: raw.githubusercontent.com, port: 443 }
45+
- { host: platform.claude.com, port: 443 }
46+
binaries:
47+
- { path: /usr/local/bin/claude }
48+
- { path: /usr/bin/node }
49+
50+
github_ssh_over_https:
51+
name: github-ssh-over-https
52+
endpoints:
53+
- host: github.com
54+
port: 443
55+
protocol: rest
56+
tls: terminate
57+
enforcement: enforce
58+
rules:
59+
# Git Smart HTTP read-only: allow clone, fetch, pull
60+
# Discovery (query string is included in path matching)
61+
- allow:
62+
method: GET
63+
path: "/**/info/refs*"
64+
# Data transfer for reads (all repos)
65+
- allow:
66+
method: POST
67+
path: "/**/git-upload-pack"
68+
# Data transfer for writes
69+
# - allow:
70+
# method: POST
71+
# path: "/**/git-receive-pack"
72+
binaries:
73+
- { path: /usr/bin/git }
74+
75+
nvidia_inference:
76+
name: nvidia-inference
77+
endpoints:
78+
- { host: integrate.api.nvidia.com, port: 443 }
79+
binaries:
80+
- { path: /usr/bin/curl }
81+
- { path: /bin/bash }
82+
- { path: /usr/local/bin/opencode }
83+
84+
# --- GitHub REST API (read-only) ---
85+
github_rest_api:
86+
name: github-rest-api
87+
endpoints:
88+
- host: api.github.com
89+
port: 443
90+
protocol: rest
91+
tls: terminate
92+
enforcement: enforce
93+
access: read-only
94+
binaries:
95+
- { path: /usr/local/bin/claude }
96+
- { path: /usr/bin/gh }
97+
98+
pypi:
99+
name: pypi
100+
endpoints:
101+
- { host: pypi.org, port: 443 }
102+
- { host: files.pythonhosted.org, port: 443 }
103+
# uv python install downloads from python-build-standalone on GitHub
104+
- { host: github.com, port: 443 }
105+
- { host: objects.githubusercontent.com, port: 443 }
106+
# uv resolves python-build-standalone release metadata via the GitHub API
107+
- { host: api.github.com, port: 443 }
108+
- { host: downloads.python.org, port: 443 }
109+
binaries:
110+
- { path: /sandbox/.venv/bin/python }
111+
- { path: /sandbox/.venv/bin/python3 }
112+
- { path: /sandbox/.venv/bin/pip }
113+
- { path: /app/.venv/bin/python }
114+
- { path: /app/.venv/bin/python3 }
115+
- { path: /app/.venv/bin/pip }
116+
- { path: /usr/local/bin/uv }
117+
# Managed Python installations from uv python install
118+
- { path: "/sandbox/.uv/python/**" }
119+
120+
vscode:
121+
name: vscode
122+
endpoints:
123+
- { host: update.code.visualstudio.com, port: 443 }
124+
# NOTE: OPA host matching uses exact equality, not glob — list hosts explicitly.
125+
- { host: az764295.vo.msecnd.net, port: 443 }
126+
- { host: vscode.download.prss.microsoft.com, port: 443 }
127+
- { host: marketplace.visualstudio.com, port: 443 }
128+
- { host: gallerycdn.vsassets.io, port: 443 }
129+
binaries:
130+
- { path: /usr/bin/curl }
131+
- { path: /usr/bin/wget }
132+
- { path: "/sandbox/.vscode-server/**" }
133+
- { path: "/sandbox/.vscode-remote-containers/**" }
134+
135+
cursor:
136+
name: cursor
137+
endpoints:
138+
- { host: cursor.blob.core.windows.net, port: 443 }
139+
# NOTE: OPA host matching uses exact equality, not glob — list hosts explicitly.
140+
- { host: api2.cursor.sh, port: 443 }
141+
- { host: repo.cursor.sh, port: 443 }
142+
- { host: download.cursor.sh, port: 443 }
143+
- { host: cursor.download.prss.microsoft.com, port: 443 }
144+
binaries:
145+
- { path: /usr/bin/curl }
146+
- { path: /usr/bin/wget }
147+
- { path: "/sandbox/.cursor-server/**" }
148+
149+
opencode:
150+
name: opencode
151+
endpoints:
152+
- host: registry.npmjs.org
153+
port: 443
154+
- host: opencode.ai
155+
port: 443
156+
- host: integrate.api.nvidia.com
157+
port: 443
158+
binaries:
159+
- path: /usr/lib/node_modules/opencode-ai/bin/.opencode
160+
- path: /usr/bin/node
161+
- path: /usr/local/bin/opencode

0 commit comments

Comments
 (0)