Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_call:
inputs:
component:
description: "Component to build (gateway, sandbox, cluster)"
description: "Component to build (gateway, cluster)"
required: true
type: string
timeout-minutes:
Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,14 @@ jobs:
with:
component: gateway

build-sandbox:
if: contains(github.event.pull_request.labels.*.name, 'e2e')
uses: ./.github/workflows/docker-build.yml
with:
component: sandbox

build-cluster:
if: contains(github.event.pull_request.labels.*.name, 'e2e')
uses: ./.github/workflows/docker-build.yml
with:
component: cluster

e2e:
needs: [build-gateway, build-sandbox, build-cluster]
needs: [build-gateway, build-cluster]
uses: ./.github/workflows/e2e-test.yml
with:
image-tag: ${{ github.sha }}
13 changes: 4 additions & 9 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,14 @@ jobs:
with:
component: gateway

build-sandbox:
uses: ./.github/workflows/docker-build.yml
with:
component: sandbox

build-cluster:
uses: ./.github/workflows/docker-build.yml
with:
component: cluster

tag-ghcr-latest:
name: Tag GHCR Images as Latest
needs: [build-gateway, build-sandbox, build-cluster]
needs: [build-gateway, build-cluster]
runs-on: build-amd64
timeout-minutes: 10
steps:
Expand All @@ -42,7 +37,7 @@ jobs:
run: |
set -euo pipefail
REGISTRY="ghcr.io/nvidia/openshell"
for component in gateway sandbox cluster; do
for component in gateway cluster; do
echo "Tagging ${REGISTRY}/${component}:${{ github.sha }} as latest..."
docker buildx imagetools create \
--prefer-index=false \
Expand All @@ -52,7 +47,7 @@ jobs:

build-python-wheels:
name: Stage Python Wheels
needs: [build-gateway, build-sandbox, build-cluster]
needs: [build-gateway, build-cluster]
runs-on: build-amd64
timeout-minutes: 120
outputs:
Expand Down Expand Up @@ -137,7 +132,7 @@ jobs:

- uses: actions/setup-python@v5
with:
python-version: "3.12"
python-version: "3.13"

- name: Install publish dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ The sandbox container includes the following tools by default:
| Category | Tools |
| ---------- | -------------------------------------------------------- |
| Agent | `claude`, `opencode`, `codex` |
| Language | `python` (3.12), `node` (22) |
| Language | `python` (3.13), `node` (22) |
| Developer | `gh`, `git`, `vim`, `nano` |
| Networking | `ping`, `dig`, `nslookup`, `nc`, `traceroute`, `netstat` |

Expand Down
4 changes: 2 additions & 2 deletions architecture/security-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ network_policies:
allowed_ips:
- "10.86.8.223/32"
binaries:
- { path: /usr/local/bin/python3.12 }
- { path: /usr/local/bin/python3.13 }
```

With this policy, both work:
Expand Down Expand Up @@ -1090,7 +1090,7 @@ network_policies:
allowed_ips:
- "10.86.8.223/32"
binaries:
- { path: /usr/local/bin/python3.12 }
- { path: /usr/local/bin/python3.13 }

inference:
allowed_routes:
Expand Down
1 change: 1 addition & 0 deletions crates/navigator-sandbox/src/l7/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ impl CertCache {

let mut params = CertificateParams::new(vec![hostname.to_string()]).into_diagnostic()?;
params.distinguished_name.push(DnType::CommonName, hostname);
params.use_authority_key_identifier_extension = true;

let leaf_cert = params
.signed_by(&leaf_key, &self.ca.ca_cert, &self.ca.ca_key)
Expand Down
4 changes: 1 addition & 3 deletions docs/tutorials/github-sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,7 @@ network_policies:
- { path: /sandbox/.venv/bin/python }
- { path: /sandbox/.venv/bin/python3 }
- { path: /sandbox/.venv/bin/pip }
- { path: /app/.venv/bin/python }
- { path: /app/.venv/bin/python3 }
- { path: /app/.venv/bin/pip }
- { path: "/sandbox/.uv/python/**/python*" }
- { path: /usr/local/bin/uv }
- { path: "/sandbox/.uv/python/**" }

Expand Down
10 changes: 7 additions & 3 deletions e2e/python/test_sandbox_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ def _policy_for_python_proxy_tests() -> sandbox_pb2.SandboxPolicy:
endpoints=[
sandbox_pb2.NetworkEndpoint(host="api.openai.com", port=443)
],
binaries=[sandbox_pb2.NetworkBinary(path="/app/.venv/bin/python")],
binaries=[
sandbox_pb2.NetworkBinary(path="/sandbox/.uv/python/**/python*")
],
)
},
)
Expand Down Expand Up @@ -373,7 +375,7 @@ def test_l4_binary_restricted_denies_wrong_binary(
"""L4-3: Policy restricted to specific binary denies others.

Policy allows /usr/bin/curl -> api.anthropic.com:443.
Python (exec_python uses /app/.venv/bin/python) should be denied.
Python (exec_python uses python) should be denied.
"""
policy = _base_policy(
network_policies={
Expand Down Expand Up @@ -438,7 +440,9 @@ def test_l4_cross_policy_denied(
endpoints=[
sandbox_pb2.NetworkEndpoint(host="api.anthropic.com", port=443),
],
binaries=[sandbox_pb2.NetworkBinary(path="/app/.venv/bin/python")],
binaries=[
sandbox_pb2.NetworkBinary(path="/sandbox/.uv/python/**/python*")
],
),
"other": sandbox_pb2.NetworkPolicyRule(
name="other",
Expand Down
6 changes: 0 additions & 6 deletions e2e/python/test_sandbox_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ def test_sandbox_venv_in_path(
assert "/sandbox/.venv/bin" in path_dirs, (
f"Expected /sandbox/.venv/bin in PATH, got: {result.stdout.strip()}"
)
# /sandbox/.venv/bin must come before /app/.venv/bin
sandbox_idx = path_dirs.index("/sandbox/.venv/bin")
app_idx = path_dirs.index("/app/.venv/bin")
assert sandbox_idx < app_idx, (
"/sandbox/.venv/bin must precede /app/.venv/bin in PATH"
)


def test_pip_install_in_sandbox(
Expand Down
4 changes: 2 additions & 2 deletions e2e/rust/tests/cli_smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ async fn sandbox_help_shows_upload_download() {
}

/// `openshell sandbox create --help` must show `--upload`, `--no-git-ignore`,
/// `--bootstrap`/`--no-bootstrap`, `--editor`, and
/// `--no-bootstrap`, `--editor`, and
/// `--auto-providers`/`--no-auto-providers`.
/// Note: `--bootstrap` is intentionally hidden (it's the default behaviour).
#[tokio::test]
async fn sandbox_create_help_shows_new_flags() {
let (output, code) = run_isolated(&["sandbox", "create", "--help"]).await;
Expand All @@ -95,7 +96,6 @@ async fn sandbox_create_help_shows_new_flags() {
for flag in [
"--upload",
"--no-git-ignore",
"--bootstrap",
"--no-bootstrap",
"--editor",
"--auto-providers",
Expand Down
2 changes: 1 addition & 1 deletion e2e/rust/tests/custom_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::io::Write;
use openshell_e2e::harness::output::strip_ansi;
use openshell_e2e::harness::sandbox::SandboxGuard;

const DOCKERFILE_CONTENT: &str = r#"FROM python:3.12-slim
const DOCKERFILE_CONTENT: &str = r#"FROM python:3.13-slim

# iproute2 is required for sandbox network namespace isolation.
RUN apt-get update && apt-get install -y --no-install-recommends iproute2 \
Expand Down
2 changes: 1 addition & 1 deletion examples/bring-your-own-container/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# The image exposes port 8080 with a /hello endpoint. Use port forwarding
# (--forward 8080 on the CLI) to reach it from your local machine.

FROM python:3.12-slim
FROM python:3.13-slim

# System tools useful for sandbox networking and debugging.
RUN apt-get update && apt-get install -y --no-install-recommends \
Expand Down
4 changes: 2 additions & 2 deletions examples/local-inference/sandbox-policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ network_policies:
- { host: pypi.org, port: 443 }
- { host: files.pythonhosted.org, port: 443 }
binaries:
- path: /usr/bin/python3.12
- path: /usr/bin/python3.13

# Direct access to the NVIDIA inference API (L7 TLS intercept).
# Used to verify that the L7 REST relay path streams responses correctly
Expand All @@ -48,4 +48,4 @@ network_policies:
enforcement: enforce
access: full
binaries:
- path: /usr/bin/python3.12
- path: /usr/bin/python3.13
2 changes: 1 addition & 1 deletion examples/private-ip-routing/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

FROM python:3.12-slim
FROM python:3.13-slim
COPY server.py /app/server.py
EXPOSE 8080
CMD ["python", "/app/server.py"]
2 changes: 1 addition & 1 deletion mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ redactions = ["*_TOKEN", "*_PASSWORD"]
experimental = true

[tools]
python = "3.12.12"
python = "3.13.12"
rust = "stable"
kubectl = "1.35.1"
uv = "0.10.2"
Expand Down
2 changes: 1 addition & 1 deletion python/openshell/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ def exec_python(
"print(result) if result is not None else None"
)

_SANDBOX_PYTHON_BIN = "/app/.venv/bin/python"
_SANDBOX_PYTHON_BIN = "python"


def _serialize_python_callable(
Expand Down
24 changes: 12 additions & 12 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading