sandbox

package
v0.3.48 Latest Latest
Warning

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

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

Documentation

Overview

Package sandbox provides sandbox/bwrap: the single source of truth for the tenant sandbox view. The same view config drives two enforcement mechanisms:

  • WrapArgv: subprocess isolation — translates the view into a bwrap argv prefix around bash / ACP subprocesses (each call runs in its own mount namespace, keeping 127.0.0.1 / the Pod network stack);
  • CheckRead / CheckWrite: in-process enforcement — for the filesystem/sandbox decorator and other in-process tools that bwrap cannot confine.

View: tmpfs masks the tenant-root parent (neighbor tenants invisible) → bind back this tenant root (rw); global root read-only with secretFiles masked; minimal system ro-binds; no --unshare-net.

Index

Constants

View Source
const (
	ModeOff   = "off"   // no wrapping, no checks — equivalent to no sandbox
	ModeAuto  = "auto"  // enable when bwrap is usable, warn and degrade otherwise (local dev only)
	ModeBwrap = "bwrap" // force enable; missing deps fail closed per FailIfUnavailable (default)
)

Sandbox modes.

Variables

This section is empty.

Functions

func New

func New(cfg Config, d Deps) (capsandbox.Service, error)

New constructs sandbox/bwrap. With mode=bwrap and unavailable deps (bwrap not in PATH or unprivileged user namespaces disabled) it fails closed per failIfUnavailable (default true).

Types

type Config

type Config struct {
	Mode              string `json:"mode"`
	FailIfUnavailable *bool  `json:"failIfUnavailable"`
	// Env marks the deployment environment: "prod"/"production" upgrades
	// mode=auto to fail-closed bwrap, so a misconfig cannot silently run
	// unsandboxed in production. Explicit config, no implicit env detection.
	Env string `json:"env"`
	// RoBinds are extra read-only binds (public read-only paths shared by all
	// tenants; source and target are the same path). Host absolute paths or
	// workspace refs (e.g. "global:share_dir", resolved per call per tenant).
	RoBinds []string `json:"roBinds"`
	// RwBinds are extra read-write binds (public writable paths shared by all
	// tenants; beware concurrent write conflicts). Host absolute paths or
	// workspace refs (missing dirs are created).
	RwBinds []string `json:"rwBinds"`
	// HidePaths are masked: directories become invisible and read-only,
	// files are masked empty. Host absolute paths or workspace refs. Applied
	// after all binds, so they can mask sensitive subpaths of system binds or
	// the global root. Resolution fails closed (a failed mask means a leak).
	HidePaths []string `json:"hidePaths"`
	// SecretFiles are sensitive files under the global root masked empty
	// (relative to the global root), default ["secrets.enc.json"].
	// Applied after the global ro-bind and ro/rwBinds.
	SecretFiles []string `json:"secretFiles"`
	// SystemBinds overrides the default minimal system read-only bind list;
	// empty uses the built-in default (/usr /bin /lib /lib64 /opt plus
	// DNS/cert files under /etc).
	SystemBinds []string `json:"systemBinds"`
	// TmpBase is the base dir on a host tmpfs (default /dev/shm/shellbwrap):
	// each tenant gets a subdir bound rw as in-sandbox /tmp. /dev/shm has its
	// own size cap (usually half of RAM), preventing tmpfs writes from eating
	// node memory. The explicit value "tmpfs" falls back to bwrap's own
	// --tmpfs /tmp (no size limit, not recommended). Must be exclusive per
	// runner instance on a shared host: startup removes leftover contents.
	TmpBase string `json:"tmpBase"`
}

Config configures sandbox/bwrap: the tenant view fields (roBinds/rwBinds/ hidePaths/secretFiles — shared by subprocess wrapping and in-process enforcement) plus the bwrap-mechanism knobs (mode/systemBinds/tmpBase/ probe-failure policy).

func (*Config) SetDefaults

func (c *Config) SetDefaults()

SetDefaults implements pluginkit.Defaulter.

func (*Config) Validate

func (c *Config) Validate() error

Validate implements pluginkit.Validator.

type Deps

type Deps struct {
	Workspace workspace.Service `json:"workspace"`
}

Deps for sandbox/bwrap.

type Sandbox

type Sandbox struct {
	// contains filtered or unexported fields
}

Sandbox is the tenant sandbox view; tenant identity is resolved from ctx on every call.

func (*Sandbox) CheckRead

func (s *Sandbox) CheckRead(ctx context.Context, path string) error

CheckRead decides per the current tenant view whether an in-process read is allowed (used by the filesystem/sandbox decorator and other in-process tools — bwrap cannot confine Go code). path is a host absolute path. When the sandbox is disabled everything is allowed (confinement falls back to the tool layer, e.g. filesystem/local root).

The read model mirrors the bwrap view's allowlist: inside the sandbox only {tenantRoot, globalRoot, roBinds, rwBinds, systemBinds} exist and everything else is invisible; accordingly an in-process read is allowed only under {tenantRoot, globalRoot, roBinds, rwBinds} (system binds are a subprocess mechanism detail — fs tools have no legitimate need to read /usr; add an explicit roBind if one ever does). Deny rules:

  • masked paths: matching hidePaths (incl. subpaths) or secretFiles;
  • everything outside the allowlist (incl. neighbor tenants and any unrelated host path).

func (*Sandbox) CheckWrite

func (s *Sandbox) CheckWrite(ctx context.Context, path string) error

CheckWrite decides per the current tenant view whether an in-process write is allowed. path is a host absolute path. Aligned with the bwrap view's read-only floor: only the tenant root and rwBinds are writable; everything else (global root, roBinds, system paths, unbound paths) is denied — the in-process equivalent of EROFS inside the sandbox.

func (*Sandbox) Enabled

func (s *Sandbox) Enabled() bool

Enabled reports whether the sandbox is active (false in off mode or after an auto-mode probe fallback). When false, WrapArgv passes through and CheckRead/CheckWrite allow everything (confinement falls back to the tool layer).

func (*Sandbox) WrapArgv

func (s *Sandbox) WrapArgv(ctx context.Context, workDir string, inner []string) ([]string, error)

WrapArgv renders bwrap args for the current tenant and wraps the inner command (e.g. ["bash","-lc",cmd] or an ACP agent command). When the sandbox is disabled, inner is returned unchanged.

View: tmpfs masks the tenant-root parent (neighbor tenants invisible) → bind back this tenant root (rw); global root read-only with secretFiles masked; minimal system ro-binds; no --unshare-net (127.0.0.1 / Pod network stack preserved).

Jump to

Keyboard shortcuts

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