NVIDIA / NVIDIA/OpenShell

feat: inject read-only files into sandbox at creation time without custom images

Open
#1,268 5 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:gateway area:sandbox feature request spike state:stale
Dominant language
Rust
Stars
8.7k
Forks
1.3k
Avg merge
2d 11h
Merged PRs (30d)
253

Description

Problem Statement

There is no mechanism to place tamper-proof configuration files inside a sandbox at creation time without building a custom container image.

The filesystem policy's read_only enforcement via Landlock is production-ready, but file delivery into read-only paths requires either baking files into an image or manually configuring driver-level bind mounts. The --upload mechanism cannot help here — it runs after Landlock is enforced as the sandbox user, so it can only write to read_write paths.

This blocks use cases where operators need to inject configuration, persona files, policy overrides, or credential bundles that the agent must read but never modify — without maintaining per-configuration image builds.

Proposed Design

Add a files field to SandboxSpec (or SandboxTemplate) that accepts a list of (path, content, mode) tuples:

message SandboxFile {
  string path = 1;      // Absolute destination path inside sandbox
  bytes content = 2;     // File content
  uint32 mode = 3;       // Unix file mode (e.g., 0o444), optional default
}

message SandboxSpec {
  // ... existing fields ...
  repeated SandboxFile files = 11;
}

Supervisor-side behavior:

  1. During prepare_filesystem() (runs as root, before Landlock), iterate over files entries
  2. Create parent directories, write file content, set ownership to root and mode to read-only
  3. Any paths covered by files entries are implicitly added to the Landlock read_only ruleset (or validated against an explicit read_only policy entry)
  4. Landlock is applied — agent process cannot modify these files

CLI surface:

openshell sandbox create \
    --file ./local/config.yaml:/etc/myapp/config.yaml \
    --file ./local/SOUL.md:/sandbox/.agent/SOUL.md:0444 \
    --policy ./policy.yaml \
    -- python /app/main.py

Key design constraints:

  • Files are written by the supervisor as root before privilege drop and Landlock enforcement — same trust model as the existing TLS CA file injection (write_ca_files())
  • Content travels through the existing gRPC channel (gateway → supervisor), not via host filesystem access — compatible with cloud/remote deployments unlike --mount
  • Size limits should be enforced (e.g., 1 MiB per file, 10 MiB total) to prevent abuse of the gRPC channel
  • Paths must pass the same validation as filesystem_policy entries (absolute, no .., max length)

Alternatives Considered

  • Custom images: Works but creates an image-per-configuration maintenance burden. Not practical when configs change frequently or vary per sandbox instance.
  • --mount / bind mounts (#500): Declined by maintainers due to security concerns with bidirectional host access and incompatibility with cloud deployments. File injection through gRPC avoids both issues — content flows through the gateway, not the host filesystem.
  • --upload to read-only paths: Not possible. Upload runs as the sandbox user after Landlock enforcement. Cannot write to read-only directories.
  • Environment variables for config: Unsuitable. The agent process can read and modify its own environment, env vars are visible in /proc/self/environ, and they don't support structured config files or binary content.

Agent Investigation

Codebase paths examined:

  • crates/openshell-sandbox/src/policy.rsFilesystemPolicy struct with read_only/read_write vecs. Enforcement infrastructure is complete.
  • crates/openshell-sandbox/src/sandbox/linux/landlock.rs — Landlock enforcement. prepare() opens PathFds as root; enforce() calls restrict_self() after privilege drop. File injection would slot between prepare and enforce.
  • crates/openshell-sandbox/src/lib.rsprepare_filesystem() (line ~2016) creates/chowns read-write dirs. write_ca_files() writes TLS certs as root before Landlock. This is the existing pattern for pre-Landlock file injection.
  • crates/openshell-sandbox/src/ssh.rs — Upload via tar-over-SSH. Runs in a child that drops privileges and enforces Landlock before exec (pre-exec hook, line ~1135). Cannot write to read-only paths.
  • proto/openshell.protoCreateSandboxRequest / SandboxSpec. No file content field exists. SandboxTemplate has environment and volume_claim_templates but no file injection.
  • crates/openshell-cli/src/run.rs — CLI sandbox creation. --upload parsed as LOCAL[:REMOTE], executes after sandbox reaches Ready state.

Related issues: #500 (host directory mounts — closed), NVIDIA/OpenShell#785 (volume mounts — open)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with proto/openshell.proto and trace CreateSandboxRequest/SandboxSpec into crates/openshell-sandbox/src/lib.rs, especially prepare_filesystem() and write_ca_files(). Then follow crates/openshell-sandbox/src/sandbox/linux/landlock.rs and crates/openshell-cli/src/run.rs. Done means files can be supplied through the API and CLI, are written before Landlock enforcement with validated paths and limits, and remain read-only to the agent.

Written by the indexing model from the issue text.

Assessment

Tech stack
grpc, rust
Domain
api, cli, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.