Documentation
¶
Overview ¶
Package sandbox builds and operates the Docker container that isolates the agent's shell and file-tool execution from the host.
The package is intentionally narrow: it owns the container lifecycle inputs (image resolution, "docker run" argument construction, file injection) but does not know about agent tools. The cmd/odek wrapper composes these helpers with the tool registry — keeping the shellTool / parallelShellTool wiring out of this package preserves the "no agent tool internals" boundary.
See docs/SANDBOXING.md for the user-facing security model.
Index ¶
Constants ¶
const DockerfileName = "Dockerfile.odek"
DockerfileName is the project-local Dockerfile name. Presence in the working directory triggers a cached image build via buildFromDockerfile.
Variables ¶
var ForbiddenMountPrefixes = []string{
"/", "/etc", "/proc", "/sys", "/boot", "/dev",
"/var", "/run", "/root", "/home",
"/var/run/docker.sock",
}
ForbiddenMountPrefixes lists host paths that volume mounts must never touch. A user could accidentally (or, in --task scenarios, be coaxed into) requesting one of these and undo the whole point of sandboxing. Mounts to these paths are dropped with a stderr warning.
Functions ¶
func BuildRunArgs ¶
BuildRunArgs returns the "docker run" argument slice for the given config — it does not execute Docker. Caller is expected to pass the already-resolved image (ResolveImage) so the same argument list can be regenerated for diagnostics without re-running the resolution.
Security defaults applied unconditionally:
--rm, --detach, --cap-drop ALL, --security-opt no-new-privileges, --tmpfs /tmp:noexec. Volume mounts are filtered against ForbiddenMountPrefixes; "host" network is forced to "none".
func InjectFiles ¶
InjectFiles copies each file under cwd into a running container via `docker cp`. Files inside cwd preserve their relative path; absolute paths outside cwd are placed by basename at /workspace/. Nested paths trigger an in-container `mkdir -p` for the parent so docker cp succeeds.
Returns the number of files actually injected. Missing files are skipped with a stderr warning (not errors), since --ctx is best-effort. Returns an error only when Docker itself fails.
func ResolveImage ¶
ResolveImage determines the Docker image for a sandbox container. Resolution order:
- cfg.Image is explicit → return it unchanged.
- Dockerfile.odek exists in CWD → build (or reuse cached) image.
- Otherwise → "alpine:latest".
Types ¶
type Config ¶
type Config struct {
Image string // Docker image (e.g. "node:20-alpine"); empty triggers Dockerfile/default resolution
Network string // "bridge" | "none" | "host"; "host" and any other value are forced to "none"
Readonly bool // Mount the working directory read-only
Memory string // Memory limit (e.g. "512m", "2g")
CPUs string // CPU limit (e.g. "0.5", "2")
User string // Container user (e.g. "1000:1000")
Env map[string]string // Extra environment variables
Volumes []string // Extra volume mounts (filtered against ForbiddenMountPrefixes)
}
Config is the resolved sandbox configuration for one agent run. All fields come from the merged config (files → env → CLI) — this struct has no notion of where values were sourced.