Documentation
¶
Overview ¶
Package sandbox provides process isolation for tool execution. Remote peer tool invocations run in isolated subprocesses to prevent access to process memory (passphrases, private keys, session tokens).
Index ¶
- Variables
- func IsWorkerMode() bool
- func RunWorker(registry ToolRegistry)
- type Config
- type ContainerConfig
- type ContainerExecutor
- type ContainerPool
- type ContainerRuntime
- type DockerRuntime
- type ExecutionRequest
- type ExecutionResult
- type Executor
- type GVisorRuntime
- type InProcessExecutor
- type NativeRuntime
- type SubprocessExecutor
- type ToolFunc
- type ToolHandler
- type ToolRegistry
Constants ¶
This section is empty.
Variables ¶
var ( ErrRuntimeUnavailable = errors.New("container runtime unavailable") // ErrContainerTimeout indicates the container execution exceeded its deadline. ErrContainerTimeout = errors.New("container execution timed out") // ErrContainerOOM indicates the container was killed due to out-of-memory. ErrContainerOOM = errors.New("container killed due to out-of-memory") )
Functions ¶
func IsWorkerMode ¶
func IsWorkerMode() bool
IsWorkerMode returns true if the process was launched as a sandbox worker.
func RunWorker ¶
func RunWorker(registry ToolRegistry)
RunWorker is the entry point for the sandbox worker subprocess. It reads an ExecutionRequest from stdin, executes the named tool from the registry, and writes an ExecutionResult to stdout. The worker exits with code 0 on success, 1 on failure.
Types ¶
type Config ¶
type Config struct {
// Enabled turns on subprocess isolation for remote tool calls.
Enabled bool
// TimeoutPerTool is the maximum duration for a single tool execution.
// Zero means no timeout.
TimeoutPerTool time.Duration
// MaxMemoryMB is a soft memory limit for the subprocess (Phase 2).
MaxMemoryMB int
}
Config controls sandbox execution behavior.
type ContainerConfig ¶
type ContainerConfig struct {
// Image is the Docker image to use for the container.
Image string
// ToolName is the name of the tool to execute.
ToolName string
// NetworkMode is the Docker network mode (e.g. "none", "bridge").
NetworkMode string
// Params are the tool invocation parameters.
Params map[string]interface{}
// MemoryLimitMB is the hard memory limit in megabytes.
MemoryLimitMB int64
// CPUQuotaUS is the CPU quota in microseconds.
CPUQuotaUS int64
// ReadOnlyRootfs mounts the root filesystem as read-only.
ReadOnlyRootfs bool
// Timeout is the maximum execution duration.
Timeout time.Duration
}
ContainerConfig defines parameters for a containerized tool execution.
type ContainerExecutor ¶
type ContainerExecutor struct {
// contains filtered or unexported fields
}
ContainerExecutor runs tool invocations through a container runtime. It probes available runtimes in priority order and falls back to native subprocess execution when no container runtime is available.
func NewContainerExecutor ¶
func NewContainerExecutor(cfg Config, containerCfg config.ContainerSandboxConfig) (*ContainerExecutor, error)
NewContainerExecutor creates a ContainerExecutor by probing runtimes in order. Priority: docker (if requested or auto) > gvisor (if requested or auto) > native. When requireContainer is true and no container runtime is available, an error is returned instead of silently falling back to NativeRuntime.
func (*ContainerExecutor) Execute ¶
func (e *ContainerExecutor) Execute(ctx context.Context, toolName string, params map[string]interface{}) (map[string]interface{}, error)
Execute runs a tool through the container runtime.
func (*ContainerExecutor) Runtime ¶
func (e *ContainerExecutor) Runtime() ContainerRuntime
Runtime returns the underlying ContainerRuntime for advanced operations.
func (*ContainerExecutor) RuntimeName ¶
func (e *ContainerExecutor) RuntimeName() string
RuntimeName returns the name of the active container runtime.
type ContainerPool ¶
type ContainerPool struct {
// contains filtered or unexported fields
}
ContainerPool manages a pool of pre-warmed containers for faster execution. It is only activated when PoolSize > 0.
func NewContainerPool ¶
func NewContainerPool(runtime ContainerRuntime, image string, size int, idleTimeout time.Duration) *ContainerPool
NewContainerPool creates a container pool with the specified size. If size is 0, the pool is effectively disabled (Acquire always returns empty).
func (*ContainerPool) Acquire ¶
func (p *ContainerPool) Acquire(ctx context.Context) (string, error)
Acquire retrieves a pre-warmed container ID from the pool. If the pool is empty, it returns an empty string (caller should create on demand).
func (*ContainerPool) Capacity ¶
func (p *ContainerPool) Capacity() int
Capacity returns the maximum pool capacity.
func (*ContainerPool) Close ¶
func (p *ContainerPool) Close()
Close drains the pool and cleans up all pre-warmed containers.
func (*ContainerPool) Release ¶
func (p *ContainerPool) Release(containerID string)
Release returns a container ID to the pool for reuse. If the pool is full or closed, the container is discarded.
func (*ContainerPool) Size ¶
func (p *ContainerPool) Size() int
Size returns the current number of containers in the pool.
type ContainerRuntime ¶
type ContainerRuntime interface {
// Run executes a tool inside a container and returns the result.
Run(ctx context.Context, cfg ContainerConfig) (*ExecutionResult, error)
// Cleanup removes containers associated with the given container ID.
Cleanup(ctx context.Context, containerID string) error
// IsAvailable checks whether the runtime is operational.
IsAvailable(ctx context.Context) bool
// Name returns the human-readable runtime name.
Name() string
}
ContainerRuntime provides an execution environment for isolated tool runs.
type DockerRuntime ¶
type DockerRuntime struct {
// contains filtered or unexported fields
}
DockerRuntime executes tools inside Docker containers.
func NewDockerRuntime ¶
func NewDockerRuntime() (*DockerRuntime, error)
NewDockerRuntime creates a DockerRuntime using the default Docker client.
func (*DockerRuntime) Cleanup ¶
func (r *DockerRuntime) Cleanup(ctx context.Context, _ string) error
Cleanup removes orphaned sandbox containers with the "lango.sandbox=true" label.
func (*DockerRuntime) IsAvailable ¶
func (r *DockerRuntime) IsAvailable(ctx context.Context) bool
IsAvailable checks if Docker daemon is reachable.
func (*DockerRuntime) Run ¶
func (r *DockerRuntime) Run(ctx context.Context, cfg ContainerConfig) (*ExecutionResult, error)
Run executes a tool inside a Docker container, communicating via stdin/stdout JSON.
type ExecutionRequest ¶
type ExecutionRequest struct {
// Version is the protocol version for backward compatibility (0 = original).
Version int `json:"version,omitempty"`
ToolName string `json:"toolName"`
Params map[string]interface{} `json:"params"`
}
ExecutionRequest is the JSON message sent to the sandbox worker via stdin.
type ExecutionResult ¶
type ExecutionResult struct {
Output map[string]interface{} `json:"output,omitempty"`
Error string `json:"error,omitempty"`
}
ExecutionResult is the JSON message received from the sandbox worker via stdout.
type Executor ¶
type Executor interface {
Execute(ctx context.Context, toolName string, params map[string]interface{}) (map[string]interface{}, error)
}
Executor runs a tool invocation, optionally in an isolated subprocess.
type GVisorRuntime ¶
type GVisorRuntime struct{}
GVisorRuntime is a ContainerRuntime implementation backed by gVisor (runsc).
gVisor provides user-space kernel isolation that is stronger than native process sandboxing but lighter than full VM-based containers. It intercepts application system calls via its Sentry component and services them without granting direct host-kernel access.
This runtime is currently a stub. All methods behave as if gVisor is not installed: IsAvailable returns false and Run returns ErrRuntimeUnavailable. To enable gVisor support, install the runsc binary (see https://gvisor.dev/docs/user_guide/install/) and replace this stub with a real implementation that delegates to the runsc OCI runtime.
func NewGVisorRuntime ¶
func NewGVisorRuntime() *GVisorRuntime
NewGVisorRuntime creates a new GVisorRuntime stub. The returned runtime always reports as unavailable until a real gVisor integration is provided.
func (*GVisorRuntime) Cleanup ¶
func (r *GVisorRuntime) Cleanup(_ context.Context, _ string) error
Cleanup is a no-op for the gVisor stub. It always returns nil because no containers are ever created.
func (*GVisorRuntime) IsAvailable ¶
func (r *GVisorRuntime) IsAvailable(_ context.Context) bool
IsAvailable always returns false for the gVisor stub, indicating that the runsc binary is not present or not configured.
func (*GVisorRuntime) Name ¶
func (r *GVisorRuntime) Name() string
Name returns "gvisor", identifying this runtime in logs and probe chains.
func (*GVisorRuntime) Run ¶
func (r *GVisorRuntime) Run(_ context.Context, _ ContainerConfig) (*ExecutionResult, error)
Run always returns ErrRuntimeUnavailable because gVisor support is not yet implemented. The cfg parameter is accepted but ignored.
type InProcessExecutor ¶
type InProcessExecutor struct {
// contains filtered or unexported fields
}
InProcessExecutor delegates directly to a ToolFunc without isolation. Use this for local/trusted tool executions where isolation is unnecessary.
func NewInProcessExecutor ¶
func NewInProcessExecutor(fn ToolFunc) *InProcessExecutor
NewInProcessExecutor wraps an existing tool function as an Executor.
type NativeRuntime ¶
type NativeRuntime struct {
// contains filtered or unexported fields
}
NativeRuntime wraps the SubprocessExecutor as a ContainerRuntime fallback. It provides process-level isolation without containerization.
func NewNativeRuntime ¶
func NewNativeRuntime(cfg Config) *NativeRuntime
NewNativeRuntime creates a NativeRuntime backed by a SubprocessExecutor.
func (*NativeRuntime) Cleanup ¶
func (r *NativeRuntime) Cleanup(_ context.Context, _ string) error
Cleanup is a no-op for native runtime — subprocesses are cleaned up on exit.
func (*NativeRuntime) IsAvailable ¶
func (r *NativeRuntime) IsAvailable(_ context.Context) bool
IsAvailable always returns true for native runtime.
func (*NativeRuntime) Run ¶
func (r *NativeRuntime) Run(ctx context.Context, cfg ContainerConfig) (*ExecutionResult, error)
Run executes the tool via the subprocess executor, adapting ContainerConfig parameters to the subprocess model.
type SubprocessExecutor ¶
type SubprocessExecutor struct {
// contains filtered or unexported fields
}
SubprocessExecutor runs tool invocations in isolated child processes. The child process inherits only PATH and HOME environment variables, preventing access to in-memory secrets of the parent process.
func NewSubprocessExecutor ¶
func NewSubprocessExecutor(cfg Config) *SubprocessExecutor
NewSubprocessExecutor creates a subprocess executor with the given config.
type ToolFunc ¶
type ToolFunc func(ctx context.Context, toolName string, params map[string]interface{}) (map[string]interface{}, error)
ToolFunc is the signature for a tool handler function.
type ToolHandler ¶
ToolHandler is a function that executes a named tool with parameters.
type ToolRegistry ¶
type ToolRegistry map[string]ToolHandler
ToolRegistry maps tool names to their handlers for the worker process.