sandbox

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2026 License: MIT Imports: 13 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
var (
	// ErrRuntimeUnavailable indicates the container runtime is not installed or accessible.
	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) Name

func (r *DockerRuntime) Name() string

Name returns the runtime name.

func (*DockerRuntime) Run

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

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.

func (*InProcessExecutor) Execute

func (e *InProcessExecutor) Execute(ctx context.Context, toolName string, params map[string]interface{}) (map[string]interface{}, error)

Execute runs the tool in the current process.

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) Name

func (r *NativeRuntime) Name() string

Name returns the runtime name.

func (*NativeRuntime) Run

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.

func (*SubprocessExecutor) Execute

func (e *SubprocessExecutor) Execute(ctx context.Context, toolName string, params map[string]interface{}) (map[string]interface{}, error)

Execute launches a child process running in sandbox worker mode and communicates via JSON over stdin/stdout.

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

type ToolHandler func(ctx context.Context, params map[string]interface{}) (interface{}, error)

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.

Directories

Path Synopsis
Package os provides OS-level kernel sandbox primitives for tool execution.
Package os provides OS-level kernel sandbox primitives for tool execution.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL