sandbox

package
v0.5.8 Latest Latest
Warning

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

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

Documentation

Overview

Package sandbox confines external plugin subprocesses. The gateway treats plugins as untrusted (they will eventually be fetched from a registry), so every plugin runs inside an OS sandbox that hides the gateway's secrets (state DB, WireGuard/Tailscale keys, the user's home directory) and, unless granted, the network.

Backends:

  • linux: user+mount+pid(+net) namespaces with a deny-by-default mount tree (ModeNamespaces); Landlock when user namespaces are unavailable (ModeLandlock, degraded).
  • darwin: seatbelt via sandbox-exec (ModeSeatbelt).
  • other: none; plugins require an explicit sandbox = "off".

The linux backends re-exec /proc/self/exe to set the sandbox up in the child before exec'ing the plugin binary. Host binaries that spawn plugins MUST call Stage1 as the first statement of main() (test packages: from TestMain) — Command and Probe fail fast if the hook was never wired, instead of hanging the go-plugin handshake.

Index

Constants

View Source
const (
	EnvBackend = "CLAWPATROL_SANDBOX_BACKEND"
	EnvStage1  = "CLAWPATROL_SANDBOX_STAGE1"
	EnvSpec    = "CLAWPATROL_SANDBOX_SPEC"
)

Env var names. EnvBackend forces a specific backend (tests, CI). EnvStage1 and EnvSpec drive the linux re-exec child and must never leak into the plugin's environment (stage-1 strips them).

Variables

This section is empty.

Functions

func BaseEnv

func BaseEnv(spec Spec) []string

BaseEnv is the minimal environment every plugin gets, sandboxed or not. Nothing from the gateway's own environment (secrets, CLAWPATROL_*, cloud credentials) is inherited; go-plugin's ClientConfig.SkipHostEnv must be set by the spawner.

func Command

func Command(spec Spec, mode Mode) (*exec.Cmd, error)

Command builds the wrapper *exec.Cmd that launches spec's plugin under mode. It sets cmd.Env (BaseEnv plus any backend control vars); go-plugin appends its handshake vars to it. It never touches Stdin/Stdout/Stderr — go-plugin owns those pipes.

func Stage1

func Stage1()

Stage1 is the env-gated re-exec entry point. Host binaries that spawn plugins must call it as the first statement of main() (test packages: from TestMain). In the parent it only records that the hook is wired. In the re-exec'd child (CLAWPATROL_SANDBOX_STAGE1 set) it sets the sandbox up and execs the plugin binary — it never returns. Setup failures print one "clawpatrol-sandbox:" line on stderr (stdout stays clean for the go-plugin handshake) and exit 87.

Types

type Availability

type Availability struct {
	// Mode is the best working backend. Never ModeOff: when nothing
	// works Probe returns an error instead.
	Mode Mode
	// Warning is non-empty when Mode is a degraded fallback; it
	// spells out exactly what the fallback does not cover.
	Warning string
	// LandlockABI is the kernel's Landlock ABI version on linux
	// (0 when unsupported). ABI >= 4 adds TCP bind/connect rules.
	LandlockABI int
}

Availability is the result of probing this host for a backend.

func Probe

func Probe() (Availability, error)

Probe detects the best available sandbox backend on this host. The result is cached per CLAWPATROL_SANDBOX_BACKEND value. A forced backend that fails its own probe is an error (it does not fall through to another backend).

type Mode

type Mode string

Mode identifies a sandbox backend.

const (
	// ModeOff runs the plugin unsandboxed (explicit operator opt-out).
	// Environment scrubbing still applies.
	ModeOff Mode = "off"
	// ModeNamespaces is the linux namespace backend.
	ModeNamespaces Mode = "namespaces"
	// ModeLandlock is the degraded linux fallback for hosts where
	// unprivileged user namespaces are blocked.
	ModeLandlock Mode = "landlock"
	// ModeSeatbelt is the macOS sandbox-exec backend.
	ModeSeatbelt Mode = "seatbelt"
)

type Network

type Network string

Network is the network capability granted to a plugin.

const (
	// NetworkNone confines the plugin to its socket dir: the only
	// channel is the gRPC unix socket shared with the gateway.
	NetworkNone Network = "none"
	// NetworkOutbound leaves the plugin in the host network (tunnel
	// plugins are the upstream transport and need to dial out).
	NetworkOutbound Network = "outbound"
)

type Spec

type Spec struct {
	// PluginName is the HCL block label, used in error text only.
	PluginName string
	// BinaryPath is the resolved plugin executable.
	BinaryPath string
	// SocketDir is the short-pathed directory holding the go-plugin
	// unix socket. It is read-write inside the sandbox at the SAME
	// absolute path, so the socket address the plugin prints on
	// stdout resolves identically for the gateway.
	SocketDir string
	// TmpDir is the plugin's private writable scratch space (HOME and
	// TMPDIR point here). Conventionally SocketDir/tmp.
	TmpDir string
	// Network is the granted network capability.
	Network Network
	// ReadPaths are extra recursive read-only grants. There is no
	// write-grant equivalent: host writes require sandbox = "off".
	ReadPaths []string
}

Spec describes one plugin launch. All paths must be absolute and symlink-resolved by the caller.

Directories

Path Synopsis
Package sandboxtest holds test helpers for code that spawns sandboxed plugin subprocesses.
Package sandboxtest holds test helpers for code that spawns sandboxed plugin subprocesses.

Jump to

Keyboard shortcuts

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