diff --git a/sandboxes/gemini/Dockerfile b/sandboxes/gemini/Dockerfile new file mode 100644 index 0000000..0e22377 --- /dev/null +++ b/sandboxes/gemini/Dockerfile @@ -0,0 +1,29 @@ +# syntax=docker/dockerfile:1.4 + +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Gemini CLI sandbox image for OpenShell +# +# Builds on the community base sandbox and adds Google Gemini CLI. +# Build: docker build -t openshell-gemini --build-arg BASE_IMAGE=openshell-base . +# Run: openshell sandbox create --from gemini + +ARG BASE_IMAGE=ghcr.io/nvidia/openshell-community/sandboxes/base:latest +FROM ${BASE_IMAGE} + +USER root + +# Install Gemini CLI (pinned for reproducibility) +RUN npm install -g @google/gemini-cli@0.35.0 + +# Copy sandbox policy +COPY policy.yaml /etc/openshell/policy.yaml + +# Create Gemini config directory +RUN mkdir -p /sandbox/.gemini && \ + chown sandbox:sandbox /sandbox/.gemini + +USER sandbox + +ENTRYPOINT ["/bin/bash"] diff --git a/sandboxes/gemini/README.md b/sandboxes/gemini/README.md new file mode 100644 index 0000000..4f4e792 --- /dev/null +++ b/sandboxes/gemini/README.md @@ -0,0 +1,28 @@ +# Gemini CLI Sandbox + +OpenShell sandbox image pre-configured with [Gemini CLI](https://github.com/google-gemini/gemini-cli) for Google AI-powered coding assistance. + +## What's Included + +- **Gemini CLI** (`@google/gemini-cli@0.35.0`) — Google Gemini AI coding agent +- Everything from the [base sandbox](../base/README.md) + +## Build + +```bash +docker build -t openshell-gemini . +``` + +To build against a specific base image: + +```bash +docker build -t openshell-gemini --build-arg BASE_IMAGE=ghcr.io/nvidia/openshell-community/sandboxes/base:latest . +``` + +## Usage + +### Create a sandbox + +```bash +openshell sandbox create --from gemini +``` diff --git a/sandboxes/gemini/policy.yaml b/sandboxes/gemini/policy.yaml new file mode 100644 index 0000000..22218f2 --- /dev/null +++ b/sandboxes/gemini/policy.yaml @@ -0,0 +1,198 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +version: 1 + +# --- Sandbox setup configuration (queried once at startup) --- + +filesystem_policy: + include_workdir: true + read_only: + - /usr + - /lib + - /proc + - /dev/urandom + - /app + - /etc + - /var/log + read_write: + - /sandbox + - /tmp + - /dev/null + +landlock: + compatibility: best_effort + +process: + run_as_user: sandbox + run_as_group: sandbox + +# --- Network policies (queried per-CONNECT request) --- +# +# Each named policy maps a set of allowed (binary, endpoint) pairs. +# Binary identity is resolved via /proc/net/tcp inode lookup + /proc/{pid}/exe. +# Ancestors (/proc/{pid}/status PPid walk) and cmdline paths are also matched. +# SHA256 integrity is enforced in Rust via trust-on-first-use, not here. + +network_policies: + claude_code: + name: claude-code + endpoints: + - { + host: api.anthropic.com, + port: 443, + protocol: rest, + enforcement: enforce, + access: full, + tls: terminate, + } + - { host: statsig.anthropic.com, port: 443 } + - { host: sentry.io, port: 443 } + - { host: raw.githubusercontent.com, port: 443 } + - { host: platform.claude.com, port: 443 } + binaries: + - { path: /usr/local/bin/claude } + - { path: /usr/bin/node } + + github_ssh_over_https: + name: github-ssh-over-https + endpoints: + - host: github.com + port: 443 + protocol: rest + tls: terminate + enforcement: enforce + rules: + # Git Smart HTTP read-only: allow clone, fetch, pull + # Discovery (query string is included in path matching) + - allow: + method: GET + path: "/**/info/refs*" + # Data transfer for reads (all repos) + - allow: + method: POST + path: "/**/git-upload-pack" + # Data transfer for writes + # - allow: + # method: POST + # path: "/**/git-receive-pack" + binaries: + - { path: /usr/bin/git } + + nvidia_inference: + name: nvidia-inference + endpoints: + - { host: integrate.api.nvidia.com, port: 443 } + binaries: + - { path: /usr/bin/curl } + - { path: /bin/bash } + - { path: /usr/local/bin/opencode } + + # --- GitHub REST API (read-only) --- + github_rest_api: + name: github-rest-api + endpoints: + - host: api.github.com + port: 443 + protocol: rest + tls: terminate + enforcement: enforce + access: read-only + binaries: + - { path: /usr/local/bin/claude } + - { path: /usr/bin/gh } + + pypi: + name: pypi + endpoints: + - { host: pypi.org, port: 443 } + - { host: files.pythonhosted.org, port: 443 } + # uv python install downloads from python-build-standalone on GitHub + - { host: github.com, port: 443 } + - { host: objects.githubusercontent.com, port: 443 } + # uv resolves python-build-standalone release metadata via the GitHub API + - { host: api.github.com, port: 443 } + - { host: downloads.python.org, port: 443 } + binaries: + - { 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: /usr/local/bin/uv } + # Managed Python installations from uv python install + - { path: "/sandbox/.uv/python/**" } + + vscode: + name: vscode + endpoints: + - { host: update.code.visualstudio.com, port: 443 } + # NOTE: OPA host matching uses exact equality, not glob — list hosts explicitly. + - { host: az764295.vo.msecnd.net, port: 443 } + - { host: vscode.download.prss.microsoft.com, port: 443 } + - { host: marketplace.visualstudio.com, port: 443 } + - { host: gallerycdn.vsassets.io, port: 443 } + binaries: + - { path: /usr/bin/curl } + - { path: /usr/bin/wget } + - { path: "/sandbox/.vscode-server/**" } + - { path: "/sandbox/.vscode-remote-containers/**" } + + cursor: + name: cursor + endpoints: + - { host: cursor.blob.core.windows.net, port: 443 } + # NOTE: OPA host matching uses exact equality, not glob — list hosts explicitly. + - { host: api2.cursor.sh, port: 443 } + - { host: repo.cursor.sh, port: 443 } + - { host: download.cursor.sh, port: 443 } + - { host: cursor.download.prss.microsoft.com, port: 443 } + binaries: + - { path: /usr/bin/curl } + - { path: /usr/bin/wget } + - { path: "/sandbox/.cursor-server/**" } + + opencode: + name: opencode + endpoints: + - host: registry.npmjs.org + port: 443 + - host: opencode.ai + port: 443 + - host: integrate.api.nvidia.com + port: 443 + binaries: + - path: /usr/lib/node_modules/opencode-ai/bin/.opencode + - path: /usr/bin/node + - path: /usr/local/bin/opencode + + copilot: + name: copilot + endpoints: + - { host: github.com, port: 443 } + - { host: api.github.com, port: 443 } + - { host: api.githubcopilot.com, port: 443 } + - { host: api.enterprise.githubcopilot.com, port: 443 } + - { host: release-assets.githubusercontent.com, port: 443 } + - { host: copilot-proxy.githubusercontent.com, port: 443 } + - { host: default.exp-tas.com, port: 443 } + binaries: + - { + path: /usr/lib/node_modules/@github/copilot/node_modules/@github/**/copilot, + } + + gemini: + name: gemini + endpoints: + - { host: generativelanguage.googleapis.com, port: 443 } + - { host: "*-aiplatform.googleapis.com", port: 443 } + - { host: cloudcode-pa.googleapis.com, port: 443 } + - { host: accounts.google.com, port: 443 } + - { host: oauth2.googleapis.com, port: 443 } + - { host: www.googleapis.com, port: 443 } + - { host: iamcredentials.googleapis.com, port: 443 } + binaries: + - { path: /usr/bin/gemini } + - { path: /usr/lib/node_modules/@google/gemini-cli/dist/index.js } + - { path: /usr/bin/node }