feat: inject read-only files into sandbox at creation time without custom images
Nobody has claimed this yet.
- 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:
- During
prepare_filesystem()(runs as root, before Landlock), iterate overfilesentries - Create parent directories, write file content, set ownership to root and mode to read-only
- Any paths covered by
filesentries are implicitly added to the Landlockread_onlyruleset (or validated against an explicitread_onlypolicy entry) - 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_policyentries (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.--uploadto 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.rs—FilesystemPolicystruct withread_only/read_writevecs. Enforcement infrastructure is complete.crates/openshell-sandbox/src/sandbox/linux/landlock.rs— Landlock enforcement.prepare()opensPathFds as root;enforce()callsrestrict_self()after privilege drop. File injection would slot between prepare and enforce.crates/openshell-sandbox/src/lib.rs—prepare_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.proto—CreateSandboxRequest/SandboxSpec. No file content field exists.SandboxTemplatehasenvironmentandvolume_claim_templatesbut no file injection.crates/openshell-cli/src/run.rs— CLI sandbox creation.--uploadparsed asLOCAL[:REMOTE], executes after sandbox reaches Ready state.
Related issues: #500 (host directory mounts — closed), NVIDIA/OpenShell#785 (volume mounts — open)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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