sandbox

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Index

Constants

View Source
const (
	WindowsCommandRunnerSubcommand = "__windows-command-runner"
	WindowsSandboxSetupSubcommand  = "__windows-sandbox-setup"
)

Hidden subcommands the main zero binary answers to when it acts as its own Windows sandbox helper (self-dispatch). The "__" prefix can never collide with a real user subcommand; internal/cli/app.go routes these before normal CLI parsing.

View Source
const EnvSandboxBackend = "ZERO_SANDBOX_BACKEND"

EnvSandboxBackend records which backend wrapped the command. sandboxEnvironment always sets it alongside EnvSandboxed, so it serves as a corroborating marker: the re-entrancy guard requires BOTH, raising the provenance bar above a single ambient flag (a stray or hand-exported ZERO_SANDBOXED=1 with no backend marker no longer forces an unsandboxed pass-through).

View Source
const EnvSandboxed = "ZERO_SANDBOXED"

EnvSandboxed marks a process that zero has already wrapped in a sandbox: every wrapped command carries ZERO_SANDBOXED=1 in its environment. When such a process spawns another command through the engine, the re-entrancy guard returns a pass-through plan instead of double-wrapping it; nested platform wrappers fail, and a second sandbox wrapper would be redundant. Unset by default.

View Source
const LinuxSandboxHelperName = "zero-linux-sandbox"
View Source
const ReasonEscalatedSandboxRequired = "unsandboxed shell command requires approval"
View Source
const ReasonNetworkBlocked = "network access requires approval"
View Source
const WindowsSandboxCommandRunnerName = "zero-windows-command-runner.exe"
View Source
const WindowsSandboxSetupName = "zero-windows-sandbox-setup.exe"

Variables

View Source
var ErrWindowsNetworkEnforcementUnavailable = errors.New("Windows sandbox network enforcement is not available")

Functions

func ApplyLandlockFilesystemProfile

func ApplyLandlockFilesystemProfile(profile PermissionProfile, cwd string) error

ApplyLandlockFilesystemProfile applies the helper's fallback Linux filesystem sandbox to the current process. The caller must exec the final command after this returns.

func ApplyLinuxNetworkDeny

func ApplyLinuxNetworkDeny() error

func ApplyUnixSocketBlock

func ApplyUnixSocketBlock() error

ApplyUnixSocketBlock installs a seccomp BPF filter on the CURRENT thread/process that denies socket(AF_UNIX, ...) with EPERM, closing the Unix-socket gap that the Linux helper's filesystem/network isolation leaves open. It must be called in the child, after fork and before exec, so the inner helper stage applies it and then execs the real command. It first sets NO_NEW_PRIVS (required to load a filter without CAP_SYS_ADMIN), then loads the program.

Not yet verified on real Linux — see seccomp.go. Callers should degrade gracefully (run without the filter, with a warning) if this returns an error, since the kernel may not support seccomp.

func BuildLinuxSandboxBwrapArgs

func BuildLinuxSandboxBwrapArgs(options LinuxSandboxBwrapOptions) ([]string, error)

func BuildLinuxSandboxCommandArgs

func BuildLinuxSandboxCommandArgs(options LinuxSandboxCommandArgsOptions) ([]string, error)

func BuildWindowsSandboxCommandArgs

func BuildWindowsSandboxCommandArgs(options WindowsSandboxCommandArgsOptions) ([]string, error)

func BuildWindowsSandboxSetupArgs

func BuildWindowsSandboxSetupArgs(options WindowsSandboxSetupArgsOptions) ([]string, error)

func FormatGrantList

func FormatGrantList(grants []Grant) string

func FormatGrantListWithCommandPrefixes

func FormatGrantListWithCommandPrefixes(grants []Grant, prefixes []CommandPrefixGrant) string

func HasRiskCategory

func HasRiskCategory(risk Risk, category string) bool

func IsAlreadySandboxed

func IsAlreadySandboxed() bool

IsAlreadySandboxed reports whether the current process is already running inside a zero-created sandbox. It requires BOTH correlated markers that sandboxEnvironment sets together — EnvSandboxed == "1" AND a non-empty EnvSandboxBackend — so a single user-set/inherited ZERO_SANDBOXED=1 cannot by itself disable wrapping. zero sets both only on genuinely wrapped commands; pass-through (direct) plans set neither.

func NormalizeCommandPrefix

func NormalizeCommandPrefix(prefix []string) ([]string, bool)

func NormalizePrefixForRoot

func NormalizePrefixForRoot(absPath, resolvedRoot string) string

NormalizePrefixForRoot resolves platform-level symlinks (e.g. macOS /var -> /private/var) in the portion of absPath that lies outside resolvedRoot, while leaving workspace-internal path components intact so that validateWorkspacePath can detect symlink traversal blocks there. It is exported because the tools layer shares it to normalize absolute paths per scope root before running its own single-root checks.

Algorithm: walk absPath component-by-component, resolving each via EvalSymlinks. Once the running resolved prefix equals resolvedRoot we are inside the root — stop resolving and append the remaining components verbatim. If a component inside the root is a symlink, leave it for validateWorkspacePath to handle. Non-existent tail components are always appended verbatim.

The walk is volume-aware so it works on Windows as well as POSIX. On Windows the same alias problem appears in a different guise — a workspace created under an 8.3 short path (C:\Users\RUNNER~1\...) is resolved by EvalSymlinks to its long form (C:\Users\runneradmin\...), so a raw short-form request would escape the long-form root unless its prefix is resolved here first. The component walk must therefore start from the volume root (C:\ or \\host\share\), not "/", or it would mangle a drive path into a drive-relative form (C:\Users -> C:Users) that the single-root checks treat as RELATIVE — failing the policy gate OPEN. On POSIX VolumeName is empty and the volume root reduces to "/", so behavior there is byte-identical to a plain "/"-rooted walk.

func ReadExclusionGlobs

func ReadExclusionGlobs(policy Policy, scope *Scope) []string

ReadExclusionGlobs returns ripgrep-style --glob exclusion args for the policy's DenyRead subtrees that fall inside the scope's workspace root, so a ripgrep-based search never descends into a read-denied subtree. For each such entry it emits `--glob`, `!<rel>` and `--glob`, `!<rel>/**`. Mirrors the read-subtree exclusion globs used by comparable executor sandboxes.

The projection is exclusions-only: a positive ripgrep glob would switch the search into whitelist mode and restrict it to only matching files, so AllowRead re-inclusion is NOT expressed here. The Go-native grep/glob tools honor AllowRead precisely via the cached predicate (Engine.ReadExclusions); this function is the coarser ripgrep-format export for an external rg-based consumer. Empty when DenyRead is unset (the default), so search behavior is unchanged.

func ResolveGrantPath

func ResolveGrantPath(env map[string]string) (string, error)

func ResolveWindowsSandboxHome

func ResolveWindowsSandboxHome(env map[string]string) (string, error)

func RunLinuxSandboxHelper

func RunLinuxSandboxHelper(args []string, stderr io.Writer) int

func RunWindowsSandboxCommandRunner

func RunWindowsSandboxCommandRunner(args []string, stderr io.Writer) int

func RunWindowsSandboxSetup

func RunWindowsSandboxSetup(args []string, stderr io.Writer) int

func ValidCommandPrefix

func ValidCommandPrefix(prefix []string) bool

func ValidateToolName

func ValidateToolName(name string) error

func ValidateWindowsNetworkPolicy

func ValidateWindowsNetworkPolicy(network NetworkPolicy) error

func ValidateWindowsSandboxSetupMarker

func ValidateWindowsSandboxSetupMarker(config WindowsSandboxSetupConfig) error

func WindowsACLPlanHash

func WindowsACLPlanHash(plan WindowsACLPlan) (string, error)

func WindowsCapabilitySIDPath

func WindowsCapabilitySIDPath(sandboxHome string) string

func WindowsCapabilitySIDsForConfig

func WindowsCapabilitySIDsForConfig(config WindowsSandboxCommandConfig) ([]string, error)

func WindowsNetworkInfraHash

func WindowsNetworkInfraHash(plan WindowsNetworkPlan) (string, error)

WindowsNetworkInfraHash fingerprints the provisioned (mode-independent) network infrastructure so the setup marker validates against the same setup for BOTH command modes. It never folds in the per-command network mode.

func WindowsOfflineMarkerSID

func WindowsOfflineMarkerSID(sandboxHome string) (string, error)

WindowsOfflineMarkerSID returns the sandbox home's offline-marker SID (minting and persisting it on first use). The persistent WFP block filter is scoped to this SID; a deny-mode command's token carries it, an allow-mode command's does not.

func WindowsSandboxSetupMarkerPath

func WindowsSandboxSetupMarkerPath(sandboxHome string) string

func WindowsSandboxSetupPathForRunner

func WindowsSandboxSetupPathForRunner(runnerPath string) string

WindowsSandboxSetupPathForRunner derives the setup helper's path from a standalone command-runner path (the sibling .exe in the release layout). Retained for that layout; self-dispatch callers use ResolveWindowsSandboxSetupHelper instead.

func WindowsShellArgs added in v0.2.0

func WindowsShellArgs(commandText string) []string

WindowsShellArgs returns cmd.exe's argv (after the executable name) for running commandText as a shell command on Windows: no wrapping quotes and no /S, so commandText reaches cmd.exe's own /C remainder parsing exactly as written. See WindowsShellCommandLine for why that matters. Used both as CommandSpec.Args for the plain (unwrapped) path and, via windowsShellCommandLineFromArgs, to recognize this same shape once it has round-tripped through the sandboxed runner's CLI argv.

func WindowsShellCommandLine added in v0.2.0

func WindowsShellCommandLine(commandText string) string

WindowsShellCommandLine builds the raw command line a Windows CreateProcess call should receive to run commandText as a shell command: "cmd.exe /d /c " followed by commandText completely unescaped.

cmd.exe's own /C remainder parsing is not CommandLineToArgvW-compatible: it applies its own quote-stripping heuristic (documented in `cmd /?`) whenever the remainder starts with a literal quote, and that heuristic does not understand backslash-escaped inner quotes the way a normal argv consumer would. A command like `python -c "print(15 / 3)"` passed through the standard exec.Cmd Args mechanism gets wrapped in an outer pair of quotes (because it contains spaces) with its own quotes escaped as \" — exactly the shape that heuristic corrupts, stripping the outer quotes but leaving the literal backslashes behind. Passing commandText through raw, exactly as the model wrote it, means cmd.exe parses it the same way it would if typed directly at an interactive prompt: a leading quoted executable path like `"C:\Program Files\foo.exe" arg` is preserved correctly by cmd.exe's own quote-preserving special case, and a command with no leading quote at all, like the python example above, is never touched by the stripping heuristic in the first place.

func WindowsUnelevatedSetupMarkerPath added in v0.2.0

func WindowsUnelevatedSetupMarkerPath(sandboxHome string) string

func WindowsWorkspaceCapabilitySID

func WindowsWorkspaceCapabilitySID(sandboxHome string, root string) (string, error)

func WindowsWritableRootCapabilitySID

func WindowsWritableRootCapabilitySID(sandboxHome string, root string) (string, error)

Types

type Action

type Action string
const (
	ActionAllow  Action = "allow"
	ActionPrompt Action = "prompt"
	ActionDeny   Action = "deny"
)

type AnalysisResult

type AnalysisResult struct {
	Interactive bool
	Destructive bool
	Network     bool
	// TooComplex is set when the script cannot be parsed (obfuscated or invalid),
	// so a caller can treat it as higher-risk instead of trusting a clean result.
	TooComplex bool
	// Programs lists the distinct top-level command names found, for diagnostics.
	Programs []string
}

AnalysisResult is a static, AST-based assessment of a shell script. It is a more precise second opinion than the regex detector in safe_command.go: because it walks the parsed command tree, a program name is only counted when it is an actual command, never when it appears inside a quoted argument (so `echo "git rebase -i"` and `node -e "require('repl').start()"` are clean).

func AnalyzeCommand

func AnalyzeCommand(script string) AnalysisResult

type Backend

type Backend struct {
	Name            BackendName `json:"name"`
	Available       bool        `json:"available"`
	Platform        string      `json:"platform,omitempty"`
	Fallback        bool        `json:"fallback"`
	CommandWrapping bool        `json:"commandWrapping"`
	NativeIsolation bool        `json:"nativeIsolation"`
	Executable      string      `json:"executable,omitempty"`
	// ExecutableArgsPrefix is prepended to a wrapped command's args before the
	// sandbox arguments. Non-empty only for the Windows self-dispatch helper,
	// where Executable is the running zero binary and this carries the hidden
	// subcommand token (e.g. "__windows-command-runner"). nil for every other
	// backend, so their serialized form is unchanged.
	ExecutableArgsPrefix []string `json:"executableArgsPrefix,omitempty"`
	Message              string   `json:"message,omitempty"`
}

func SelectBackend

func SelectBackend(options BackendOptions) Backend

func (Backend) BuildPlan

func (backend Backend) BuildPlan(workspaceRoot string, policy Policy) BackendPlan

func (Backend) Capabilities

func (backend Backend) Capabilities(policy Policy) []BackendCapability

func (Backend) DowngradeReason

func (backend Backend) DowngradeReason(policy Policy) string

func (Backend) EnforcementLevel

func (backend Backend) EnforcementLevel(policy Policy) EnforcementLevel

func (Backend) SandboxEnvMarkers

func (backend Backend) SandboxEnvMarkers(policy Policy) []string

func (Backend) SupportLevel

func (backend Backend) SupportLevel() BackendSupportLevel

func (Backend) TargetBackend

func (backend Backend) TargetBackend() BackendName

func (Backend) Warnings

func (backend Backend) Warnings() []string

type BackendCapability

type BackendCapability struct {
	Key    string           `json:"key"`
	Status CapabilityStatus `json:"status"`
	Detail string           `json:"detail"`
}

type BackendName

type BackendName string
const (
	BackendNone                   BackendName = "none"
	BackendMacOSSeatbelt          BackendName = "macos-seatbelt"
	BackendLinuxBwrap             BackendName = "linux-bwrap"
	BackendLinuxLandlock          BackendName = "linux-landlock"
	BackendWindowsRestrictedToken BackendName = "windows-restricted-token"
	BackendWindowsElevated        BackendName = "windows-elevated"
	BackendUnavailable            BackendName = "unavailable"
	// BackendWSL records that WSL was detected but native Linux sandbox wrapping
	// is unavailable or unreliable in that environment.
	BackendWSL BackendName = "wsl"
)

func TargetBackendForPlatform

func TargetBackendForPlatform(goos string, wsl bool) BackendName

type BackendOptions

type BackendOptions struct {
	GOOS             string
	LookupExecutable func(string) (string, error)
}

type BackendPlan

type BackendPlan struct {
	Backend                 Backend             `json:"backend"`
	TargetBackend           BackendName         `json:"targetBackend"`
	WorkspaceRoot           string              `json:"workspaceRoot"`
	Policy                  Policy              `json:"policy"`
	PermissionProfile       PermissionProfile   `json:"permissionProfile"`
	CommandWrapped          bool                `json:"commandWrapped"`
	SandboxEnvMarkers       []string            `json:"sandboxEnvMarkers,omitempty"`
	EnforcementLevel        EnforcementLevel    `json:"enforcementLevel"`
	DowngradeReason         string              `json:"downgradeReason,omitempty"`
	SupportLevel            BackendSupportLevel `json:"supportLevel"`
	RequiresPlatformSandbox bool                `json:"requiresPlatformSandbox"`
	Capabilities            []BackendCapability `json:"capabilities"`
	Restrictions            []string            `json:"restrictions"`
	Warnings                []string            `json:"warnings,omitempty"`
}

type BackendSupportLevel

type BackendSupportLevel string
const (
	BackendSupportNative      BackendSupportLevel = "native"
	BackendSupportUnavailable BackendSupportLevel = "unavailable"
)

type Block

type Block struct {
	Code        BlockCode `json:"code"`
	ToolName    string    `json:"toolName,omitempty"`
	Action      Action    `json:"action"`
	Risk        Risk      `json:"risk"`
	Path        string    `json:"path,omitempty"`
	Reason      string    `json:"reason"`
	Recoverable bool      `json:"recoverable"`
}

func (Block) Error

func (block Block) Error() string

type BlockCode

type BlockCode string
const (
	BlockContextCanceled    BlockCode = "context_canceled"
	BlockDeniedPermission   BlockCode = "denied_permission"
	BlockOutsideWorkspace   BlockCode = "outside_workspace"
	BlockSymlinkTraversal   BlockCode = "symlink_traversal"
	BlockNetwork            BlockCode = "network"
	BlockDestructiveCommand BlockCode = "destructive_command"
	BlockPersistentDeny     BlockCode = "persistent_deny"
	// BlockDenied is the catch-all for a denied decision that carries no more
	// specific block code.
	BlockDenied BlockCode = "denied"
)

type CapabilityStatus

type CapabilityStatus string
const (
	CapabilityNative      CapabilityStatus = "native"
	CapabilityPreflight   CapabilityStatus = "preflight"
	CapabilityUnavailable CapabilityStatus = "unavailable"
	CapabilityDisabled    CapabilityStatus = "disabled"
)

type CommandPlan

type CommandPlan struct {
	Backend                 Backend           `json:"backend"`
	TargetBackend           BackendName       `json:"targetBackend"`
	WorkspaceRoot           string            `json:"workspaceRoot"`
	Policy                  Policy            `json:"policy"`
	PermissionProfile       PermissionProfile `json:"permissionProfile"`
	Wrapped                 bool              `json:"wrapped"`
	SandboxEnvMarkers       []string          `json:"sandboxEnvMarkers,omitempty"`
	EnforcementLevel        EnforcementLevel  `json:"enforcementLevel"`
	DowngradeReason         string            `json:"downgradeReason,omitempty"`
	RequiresPlatformSandbox bool              `json:"requiresPlatformSandbox"`
	Name                    string            `json:"name"`
	Args                    []string          `json:"args"`
	Dir                     string            `json:"dir,omitempty"`
	Env                     []string          `json:"env,omitempty"`
	SandboxDir              string            `json:"sandboxDir,omitempty"`
	// MonitorTag, when non-empty, is the unique marker embedded in the
	// sandbox-exec profile's denial messages; a caller passes it to
	// StartDenialMonitor to capture what the sandbox blocked. Empty unless
	// Policy.MonitorDenials is set on a macOS sandbox-exec plan.
	MonitorTag string `json:"monitorTag,omitempty"`
	// Notes records auditable least-privilege downgrade notes, such as native
	// isolation being unavailable in the selected environment. Surfaced to the
	// operator; never affects enforcement.
	Notes []string `json:"notes,omitempty"`
	// contains filtered or unexported fields
}

func (CommandPlan) Cleanup

func (plan CommandPlan) Cleanup()

Cleanup releases any resources the plan holds. It is safe to call on a zero plan and to call more than once.

type CommandPrefixGrant

type CommandPrefixGrant struct {
	ToolName   string   `json:"toolName"`
	Prefix     []string `json:"prefix"`
	ApprovedAt string   `json:"approvedAt,omitempty"`
	Reason     string   `json:"reason,omitempty"`
	Session    bool     `json:"session,omitempty"`
}

type CommandPrefixInput

type CommandPrefixInput struct {
	ToolName string
	Prefix   []string
	Reason   string
}

type CommandSpec

type CommandSpec struct {
	Name string
	Args []string
	Dir  string
	Env  []string
}

type Decision

type Decision struct {
	Action       Action `json:"action"`
	Reason       string `json:"reason,omitempty"`
	Risk         Risk   `json:"risk"`
	GrantMatched bool   `json:"grantMatched,omitempty"`
	Grant        *Grant `json:"grant,omitempty"`
	Block        *Block `json:"block,omitempty"`
	// AutoAllowed marks an allow that the sandbox itself authorized without a user
	// prompt or persistent grant, such as a workspace-write file mutation or an
	// opted-in sandboxed shell command. Enforcement points treat it like a
	// grant-authorized allow so a prompt tool runs without a separately-recorded
	// PermissionGranted.
	AutoAllowed bool `json:"autoAllowed,omitempty"`
}

func (Decision) ErrorString

func (decision Decision) ErrorString() string

type DenialMonitor

type DenialMonitor struct{}

DenialMonitor is a no-op outside macOS: the `log stream` seatbelt-denial feed is macOS-specific, and the bubblewrap backend surfaces failures differently.

func StartDenialMonitor

func StartDenialMonitor(_ context.Context, _ string) *DenialMonitor

StartDenialMonitor returns a no-op monitor on non-macOS platforms.

func (*DenialMonitor) Stop

func (monitor *DenialMonitor) Stop() []string

Stop returns no blocks on non-macOS platforms.

type EnforcementLevel

type EnforcementLevel string
const (
	EnforcementNative EnforcementLevel = "native"
	// EnforcementUnelevated is the Windows-only middle tier used when the
	// elevated `zero sandbox setup` has not run: commands still wrap through the
	// command runner with a write-restricted token and workspace ACLs (which the
	// runner can apply without Administrator rights), but the WFP network
	// filters are absent, so network isolation stays with the in-process
	// approval gate.
	EnforcementUnelevated EnforcementLevel = "unelevated"
	EnforcementDegraded   EnforcementLevel = "degraded"
	EnforcementDisabled   EnforcementLevel = "disabled"
)

type Engine

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

func NewEngine

func NewEngine(options EngineOptions) *Engine

func (*Engine) ApprovedCommandPrefixes

func (engine *Engine) ApprovedCommandPrefixes() []CommandPrefixGrant

func (*Engine) BuildCommandPlan

func (engine *Engine) BuildCommandPlan(spec CommandSpec) (CommandPlan, error)

func (*Engine) CanPersistGrants

func (engine *Engine) CanPersistGrants() bool

func (*Engine) CommandContext

func (engine *Engine) CommandContext(ctx context.Context, spec CommandSpec) (*exec.Cmd, CommandPlan, error)

func (*Engine) Evaluate

func (engine *Engine) Evaluate(ctx context.Context, request Request) Decision

func (*Engine) Grant

func (engine *Engine) Grant(input GrantInput) (Grant, error)

func (*Engine) GrantCommandPrefix

func (engine *Engine) GrantCommandPrefix(input CommandPrefixInput) (CommandPrefixGrant, error)

func (*Engine) GrantCommandPrefixForSession

func (engine *Engine) GrantCommandPrefixForSession(toolName string, prefix []string)

func (*Engine) GrantForSession

func (engine *Engine) GrantForSession(input GrantInput) (Grant, error)

func (*Engine) GrantRequestPermissions

func (engine *Engine) GrantRequestPermissions(profile RequestPermissionProfile, scope PermissionGrantScope) (func(), error)

func (*Engine) LookupCommandPrefix

func (engine *Engine) LookupCommandPrefix(toolName string, command []string) (CommandPrefixGrant, bool)

func (*Engine) LookupCommandPrefixForSession

func (engine *Engine) LookupCommandPrefixForSession(toolName string, command []string) (CommandPrefixGrant, bool)

func (*Engine) Precheck

func (engine *Engine) Precheck(ctx context.Context, request Request) []Block

Precheck reports the sandbox blocks that would block a tool request BEFORE it executes, so a caller (e.g. a batch confirmation or a "would this run?" check) can fail fast and surface the reason instead of discovering it mid-run. It reuses Evaluate, so policy is never duplicated: a request the engine would allow or merely prompt for yields no blocks; a denied request yields its block. A nil engine (sandbox disabled) yields no blocks.

func (*Engine) ReadExclusionGlobs

func (engine *Engine) ReadExclusionGlobs() []string

ReadExclusionGlobs returns the ripgrep-style --glob exclusion args for this engine's policy + scope (see the package-level ReadExclusionGlobs). Empty when DenyRead is unset or the engine has no scope.

func (*Engine) ReadExclusions

func (engine *Engine) ReadExclusions() *ReadExclusions

ReadExclusions returns the resolved DenyRead/AllowRead exclusion matcher for this engine's policy, resolving each policy entry ONCE. The search tools build it a single time per run and reuse it across the whole walk so the predicates don't re-run Abs/EvalSymlinks per visited path. Returns nil for a nil engine (the matcher's methods treat nil as "exclude nothing").

func (*Engine) Scope

func (engine *Engine) Scope() *Scope

Scope returns the engine's shared write scope (nil when the engine was built without a workspace root and no explicit Scope option). The TUI uses it for /add-dir.

func (*Engine) UnsandboxedExecutionAllowed

func (engine *Engine) UnsandboxedExecutionAllowed() bool

UnsandboxedExecutionAllowed reports whether an escalated shell attempt may bypass the native sandbox without dropping active denied-read restrictions.

type EngineOptions

type EngineOptions struct {
	WorkspaceRoot string
	Policy        Policy
	Store         *GrantStore
	Backend       Backend
	Scope         *Scope
}

type FileSystemAccessMode

type FileSystemAccessMode string
const (
	FileSystemAccessRead  FileSystemAccessMode = "read"
	FileSystemAccessWrite FileSystemAccessMode = "write"
	FileSystemAccessDeny  FileSystemAccessMode = "deny"
)

type FileSystemPath

type FileSystemPath struct {
	Kind    string `json:"kind,omitempty"`
	Type    string `json:"type,omitempty"`
	Path    string `json:"path,omitempty"`
	Pattern string `json:"pattern,omitempty"`
}

func (*FileSystemPath) UnmarshalJSON

func (path *FileSystemPath) UnmarshalJSON(data []byte) error

type FileSystemPermissions

type FileSystemPermissions struct {
	Read             []string                 `json:"read,omitempty"`
	Write            []string                 `json:"write,omitempty"`
	DenyRead         []string                 `json:"deny_read,omitempty"`
	GlobScanMaxDepth *int                     `json:"glob_scan_max_depth,omitempty"`
	Entries          []FileSystemSandboxEntry `json:"entries,omitempty"`
}

type FileSystemPolicy

type FileSystemPolicy struct {
	Kind                 FileSystemPolicyKind `json:"kind"`
	ReadRoots            []string             `json:"readRoots,omitempty"`
	WriteRoots           []WritableRoot       `json:"writeRoots,omitempty"`
	DenyRead             []string             `json:"denyRead,omitempty"`
	DenyWrite            []string             `json:"denyWrite,omitempty"`
	IncludePlatformRoots bool                 `json:"includePlatformRoots,omitempty"`
	AllowTemp            bool                 `json:"allowTemp,omitempty"`
}

type FileSystemPolicyKind

type FileSystemPolicyKind string
const (
	FileSystemRestricted   FileSystemPolicyKind = "restricted"
	FileSystemUnrestricted FileSystemPolicyKind = "unrestricted"
	FileSystemExternal     FileSystemPolicyKind = "external"
)

type FileSystemSandboxEntry

type FileSystemSandboxEntry struct {
	Path   FileSystemPath       `json:"path"`
	Access FileSystemAccessMode `json:"access"`
}

type Grant

type Grant struct {
	ToolName   string        `json:"toolName"`
	Scope      string        `json:"scope,omitempty"`     // absolute path, host, or "" for tool-wide
	ScopeKind  ScopeKind     `json:"scopeKind,omitempty"` // file | dir | host | "" (tool-wide)
	Decision   GrantDecision `json:"decision"`
	ApprovedAt string        `json:"approvedAt"`
	Reason     string        `json:"reason,omitempty"`
	Session    bool          `json:"session,omitempty"`
}

type GrantDecision

type GrantDecision string
const (
	GrantAllow GrantDecision = "allow"
	GrantDeny  GrantDecision = "deny"
)

func NormalizeGrantDecision

func NormalizeGrantDecision(value GrantDecision) (GrantDecision, error)

type GrantInput

type GrantInput struct {
	ToolName string
	Decision GrantDecision
	Reason   string
	// Scope is the raw path or host the grant covers; ScopeKind classifies it.
	// engine.Grant resolves path scopes to absolute paths and normalizes host
	// scopes before persisting. Both empty means a tool-wide grant.
	Scope     string
	ScopeKind ScopeKind
}

type GrantLookup

type GrantLookup struct {
	Matched bool  `json:"matched"`
	Grant   Grant `json:"grant,omitempty"`
}

type GrantStore

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

func NewGrantStore

func NewGrantStore(options StoreOptions) (*GrantStore, error)

func (*GrantStore) Clear

func (store *GrantStore) Clear() (int, error)

func (*GrantStore) FilePath

func (store *GrantStore) FilePath() string

func (*GrantStore) Grant

func (store *GrantStore) Grant(input GrantInput) (Grant, error)

func (*GrantStore) GrantCommandPrefix

func (store *GrantStore) GrantCommandPrefix(input CommandPrefixInput) (CommandPrefixGrant, error)

func (*GrantStore) List

func (store *GrantStore) List() ([]Grant, error)

func (*GrantStore) ListCommandPrefixes

func (store *GrantStore) ListCommandPrefixes() ([]CommandPrefixGrant, error)

func (*GrantStore) Lookup

func (store *GrantStore) Lookup(toolName string, reqScope string) (GrantLookup, error)

Lookup returns the grant that governs a tool call whose normalized scope is reqScope (empty for a tool-wide request, e.g. a shell command with no cwd). Among the tool's grants that cover the request, a covering deny wins outright; otherwise the most-specific covering allow is returned.

func (*GrantStore) LookupCommandPrefix

func (store *GrantStore) LookupCommandPrefix(toolName string, command []string) (CommandPrefixGrant, bool, error)

func (*GrantStore) Revoke

func (store *GrantStore) Revoke(toolName string) (int, error)

func (*GrantStore) RevokePath

func (store *GrantStore) RevokePath(toolName string, scopePath string) (int, error)

RevokePath revokes only the grants for toolName whose scope matches scopePath (a file or directory grant), leaving tool-wide and other-path grants intact. scopePath is canonicalized to an absolute, cleaned path the same way stored scopes are, so the caller can pass either an absolute path or one relative to the working directory (or copy it from `grants list`). Returns the number of grants removed.

type InteractiveCommandResult

type InteractiveCommandResult struct {
	// Interactive is true when the command launches a program that waits for
	// terminal input the agent cannot supply.
	Interactive bool
	// Command is the matched program/segment (e.g. "vim", "git rebase -i").
	Command string
	// Reason is a short human-readable explanation of why it would hang.
	Reason string
	// Suggestion is an actionable non-interactive alternative.
	Suggestion string
}

InteractiveCommandResult describes the outcome of inspecting a shell command for interactive programs that would hang a non-interactive agent (the agent has no TTY to type into, so an editor/pager/REPL would block until timeout).

func DetectInteractiveCommand

func DetectInteractiveCommand(command string, goos string) InteractiveCommandResult

DetectInteractiveCommand inspects a shell command for interactive programs that would block a non-interactive agent. goos selects platform-specific rules (pass "" to use the host runtime.GOOS).

type LinuxSandboxBwrapOptions

type LinuxSandboxBwrapOptions struct {
	Config     LinuxSandboxHelperConfig
	HelperPath string
}

type LinuxSandboxCommandArgsOptions

type LinuxSandboxCommandArgsOptions struct {
	SandboxPolicyCWD     string
	CommandCWD           string
	PermissionProfile    PermissionProfile
	UseLandlock          bool
	ApplySeccompThenExec bool
	BlockUnixSockets     bool
	NoProc               bool
	Command              []string
}

type LinuxSandboxHelperCommand

type LinuxSandboxHelperCommand struct {
	Name       string
	ArgsPrefix []string
	Dir        string
}

type LinuxSandboxHelperConfig

type LinuxSandboxHelperConfig struct {
	SandboxPolicyCWD     string
	CommandCWD           string
	PermissionProfile    PermissionProfile
	UseLandlock          bool
	ApplySeccompThenExec bool
	BlockUnixSockets     bool
	NoProc               bool
	Command              []string
}

func ParseLinuxSandboxHelperArgs

func ParseLinuxSandboxHelperArgs(args []string) (LinuxSandboxHelperConfig, error)

type NetworkMode

type NetworkMode string
const (
	NetworkDeny  NetworkMode = "deny"
	NetworkAllow NetworkMode = "allow"
)

func NormalizeNetworkMode

func NormalizeNetworkMode(value NetworkMode) NetworkMode

type NetworkPermissions

type NetworkPermissions struct {
	Enabled *bool `json:"enabled,omitempty"`
}

type NetworkPolicy

type NetworkPolicy struct {
	Mode NetworkMode `json:"mode"`
}

type Permission

type Permission string
const (
	PermissionAllow  Permission = "allow"
	PermissionPrompt Permission = "prompt"
	PermissionDeny   Permission = "deny"
)

func NormalizePermission

func NormalizePermission(value Permission) Permission

type PermissionGrantScope

type PermissionGrantScope string
const (
	PermissionGrantScopeTurn    PermissionGrantScope = "turn"
	PermissionGrantScopeSession PermissionGrantScope = "session"
)

type PermissionMode

type PermissionMode string
const (
	PermissionModeAuto PermissionMode = "auto"
	PermissionModeAsk  PermissionMode = "ask"
	PermissionUnsafe   PermissionMode = "unsafe"
)

func NormalizePermissionMode

func NormalizePermissionMode(value PermissionMode) PermissionMode

type PermissionProfile

type PermissionProfile struct {
	FileSystem FileSystemPolicy `json:"fileSystem"`
	Network    NetworkPolicy    `json:"network"`
}

func DefaultPermissionProfile

func DefaultPermissionProfile(workspaceRoot string) PermissionProfile

func PermissionProfileFromPolicy

func PermissionProfileFromPolicy(workspaceRoot string, policy Policy, scope *Scope) PermissionProfile

func (PermissionProfile) RequiresPlatformSandbox

func (profile PermissionProfile) RequiresPlatformSandbox() bool

type Policy

type Policy struct {
	Mode             PolicyMode  `json:"mode"`
	Network          NetworkMode `json:"network"`
	EnforceWorkspace bool        `json:"enforceWorkspace"`
	// BlockUnixSockets, when true on the Linux helper backend, installs a
	// best-effort seccomp filter in the inner helper stage that denies AF_UNIX
	// socket creation. It is an extra hardening layer over the native sandbox and
	// is ignored on non-Linux backends.
	BlockUnixSockets bool `json:"blockUnixSockets,omitempty"`
	// MonitorDenials, when true on macOS, tags the sandbox-exec profile's denials
	// and tails `log stream` for them so blocked operations can be surfaced back to
	// the agent. Off by default: it starts a `log stream` subprocess per command and
	// appends a <sandbox_blocks> note to the command's stderr, so it is opt-in.
	// Ignored on non-macOS backends, and a no-op where the OS does not deliver
	// seatbelt denials to the unified log.
	MonitorDenials bool `json:"monitorDenials,omitempty"`
	// AllowRead/DenyRead/AllowWrite/DenyWrite are fine-grained path lists layered
	// ON TOP of the workspace + Scope guards; they never bypass the symlink /
	// out-of-workspace protections. Each entry is home-expanded, made absolute, and
	// symlink-resolved (an entry that does not exist is dropped). All default empty,
	// so an unconfigured policy behaves exactly as before. Semantics:
	//
	//   - Read: a path readable under the base workspace/Scope guard is denied if it
	//     falls under a DenyRead entry, UNLESS a more-specific AllowRead entry (one
	//     nested inside that DenyRead entry) re-includes it. AllowRead only
	//     re-includes within a DenyRead carve-out; it never extends reads beyond the
	//     workspace.
	//   - Write: DenyWrite wins over everything; otherwise a path writable under the
	//     workspace/Scope guard is allowed; otherwise an absolute path under an
	//     AllowWrite root is allowed; otherwise it is denied. AllowWrite roots are
	//     also reflected in the OS backend write binds, and on sandbox-exec DenyWrite
	//     entries are emitted as explicit deny rules so the precedence holds for
	//     shell commands too.
	AllowRead  []string `json:"allowRead,omitempty"`
	DenyRead   []string `json:"denyRead,omitempty"`
	AllowWrite []string `json:"allowWrite,omitempty"`
	DenyWrite  []string `json:"denyWrite,omitempty"`
}

func DefaultPolicy

func DefaultPolicy() Policy

type PolicyMode

type PolicyMode string
const (
	ModeDisabled PolicyMode = "disabled"
	ModeEnforce  PolicyMode = "enforce"
)

type ReadExclusions

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

ReadExclusions holds the resolved DenyRead/AllowRead roots for a policy so a search walk resolves each policy entry ONCE (Abs/EvalSymlinks) and reuses the result across every visited path, rather than re-resolving per path. Build it with Engine.ReadExclusions and reuse it for the whole grep/glob walk.

func (*ReadExclusions) Active

func (rx *ReadExclusions) Active() bool

Active reports whether any DenyRead root is configured. When false the exclusions are a no-op and the search behaves exactly as before.

func (*ReadExclusions) DirExcluded

func (rx *ReadExclusions) DirExcluded(path string) bool

DirExcluded reports whether a directory subtree can be skipped wholesale during a walk: it is read-denied AND contains no nested AllowRead root (descending is required to reach a re-included subtree). When it returns false on a denied dir because of a nested allow, PathExcluded still filters the denied siblings.

func (*ReadExclusions) PathExcluded

func (rx *ReadExclusions) PathExcluded(path string) bool

PathExcluded reports whether reading path is excluded by DenyRead, honoring a more-specific AllowRead re-inclusion. It is the per-file predicate for a walk.

type Request

type Request struct {
	WorkspaceRoot     string         `json:"workspaceRoot,omitempty"`
	ToolName          string         `json:"toolName"`
	SideEffect        SideEffect     `json:"sideEffect"`
	Permission        Permission     `json:"permission"`
	PermissionGranted bool           `json:"permissionGranted,omitempty"`
	PermissionMode    PermissionMode `json:"permissionMode"`
	Args              map[string]any `json:"args,omitempty"`
	Reason            string         `json:"reason,omitempty"`
}

type RequestPermissionProfile

type RequestPermissionProfile struct {
	Network    *NetworkPermissions    `json:"network,omitempty"`
	FileSystem *FileSystemPermissions `json:"file_system,omitempty"`
}

func NormalizeRequestPermissionProfile

func NormalizeRequestPermissionProfile(profile RequestPermissionProfile, basePath string) (RequestPermissionProfile, error)

func RequestPermissionGrantProfile

func RequestPermissionGrantProfile(profile RequestPermissionProfile) (RequestPermissionProfile, error)

RequestPermissionGrantProfile returns the effective grant profile the engine can enforce. File-like read/write requests become their normalized parent directory roots, matching GrantRequestPermissions and native sandbox profiles.

func (RequestPermissionProfile) Empty

func (profile RequestPermissionProfile) Empty() bool

type RequestPermissionsResponse

type RequestPermissionsResponse struct {
	Permissions      RequestPermissionProfile `json:"permissions"`
	Scope            PermissionGrantScope     `json:"scope"`
	StrictAutoReview bool                     `json:"strict_auto_review,omitempty"`
}

type Risk

type Risk struct {
	Level      RiskLevel `json:"level"`
	Categories []string  `json:"categories,omitempty"`
	Reason     string    `json:"reason,omitempty"`
}

func Classify

func Classify(request Request) Risk

type RiskLevel

type RiskLevel string
const (
	RiskLow      RiskLevel = "low"
	RiskMedium   RiskLevel = "medium"
	RiskHigh     RiskLevel = "high"
	RiskCritical RiskLevel = "critical"
)

type SandboxExecutionRequest

type SandboxExecutionRequest struct {
	Command                 CommandSpec         `json:"command"`
	WorkspaceRoot           string              `json:"workspaceRoot"`
	PermissionProfile       PermissionProfile   `json:"permissionProfile"`
	Backend                 Backend             `json:"backend"`
	TargetBackend           BackendName         `json:"targetBackend"`
	CommandWrapped          bool                `json:"commandWrapped"`
	SandboxEnvMarkers       []string            `json:"sandboxEnvMarkers,omitempty"`
	EnforcementLevel        EnforcementLevel    `json:"enforcementLevel"`
	DowngradeReason         string              `json:"downgradeReason,omitempty"`
	SupportLevel            BackendSupportLevel `json:"supportLevel"`
	RequiresPlatformSandbox bool                `json:"requiresPlatformSandbox"`
}

func (SandboxExecutionRequest) BackendPlan

func (request SandboxExecutionRequest) BackendPlan(policy Policy) BackendPlan

type SandboxManager

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

func NewSandboxManager

func NewSandboxManager(options SandboxManagerOptions) SandboxManager

func (SandboxManager) Backend

func (manager SandboxManager) Backend() Backend

func (SandboxManager) BuildCommandPlan

func (manager SandboxManager) BuildCommandPlan(request SandboxManagerRequest) (CommandPlan, error)

func (SandboxManager) BuildExecutionRequest

func (manager SandboxManager) BuildExecutionRequest(request SandboxManagerRequest) (SandboxExecutionRequest, error)

type SandboxManagerOptions

type SandboxManagerOptions struct {
	GOOS             string
	LookupExecutable func(string) (string, error)
	Backend          Backend
}

type SandboxManagerRequest

type SandboxManagerRequest struct {
	WorkspaceRoot     string
	Command           CommandSpec
	Policy            Policy
	Scope             *Scope
	Profile           PermissionProfile
	Preference        SandboxPreference
	ValidateExecution bool
}

type SandboxPreference

type SandboxPreference string
const (
	SandboxPreferenceAuto    SandboxPreference = "auto"
	SandboxPreferenceRequire SandboxPreference = "require"
	SandboxPreferenceForbid  SandboxPreference = "forbid"
)

type Scope

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

Scope is the shared set of directories the sandbox allows writes in: the workspace root plus zero or more user-granted extra roots. One instance is created per run and shared by the policy engine, the OS command runners, and the file tools, so a mid-session Add is immediately visible to every layer.

func NewScope

func NewScope(workspaceRoot string, extras []string) (*Scope, error)

NewScope builds a scope for workspaceRoot plus the given extra roots. The workspace root is normalized best-effort (it may not exist in tests); every extra root must normalize strictly via Add and an invalid one fails the whole construction so a bad --add-dir/config entry surfaces at startup.

func (*Scope) Add

func (s *Scope) Add(path string) (string, error)

Add grants write access under path. The path must be an existing directory; it is home-expanded, made absolute, and symlink-resolved before being trusted, and the filesystem root is rejected outright. Adding a path already covered by an existing root is an idempotent success.

func (*Scope) AddRead

func (s *Scope) AddRead(path string) (string, error)

AddRead grants read-only access under path. If the path is already covered by a writable root, no separate read root is stored.

func (*Scope) AddTemporaryRead

func (s *Scope) AddTemporaryRead(path string) (string, func(), error)

func (*Scope) AddTemporaryWrite

func (s *Scope) AddTemporaryWrite(path string) (string, func(), error)

func (*Scope) ReadRoots

func (s *Scope) ReadRoots() []string

ReadRoots returns the workspace root, write roots, and read-only roots as a copy. Write roots are included because anything writable must also be readable by the tool layer and native sandbox profile.

func (*Scope) Roots

func (s *Scope) Roots() []string

Roots returns the workspace root first, then the extra roots, as a copy.

func (*Scope) WorkspaceRoot

func (s *Scope) WorkspaceRoot() string

WorkspaceRoot returns the resolved workspace root. It is safe to call without acquiring the lock because workspaceRoot is immutable after construction.

type ScopeKind

type ScopeKind string

ScopeKind classifies what a grant's scope covers. An empty kind is a tool-wide grant (it authorizes the whole tool, the pre-scoping behavior); a file scope matches one exact path; a dir scope matches the directory and any descendant; a host scope matches one normalized network host.

const (
	ScopeToolWide ScopeKind = ""
	ScopeFile     ScopeKind = "file"
	ScopeDir      ScopeKind = "dir"
	ScopeHost     ScopeKind = "host"
)

func DeriveScope

func DeriveScope(toolName string, args map[string]any) (string, ScopeKind)

DeriveScope inspects a tool call's arguments and returns the raw (un-resolved) scope string and its kind. It returns ("", ScopeToolWide) when no scoped argument is present, the value is not a string, or the value points at the workspace root (".") -- in those cases the grant is plainly tool-wide.

type SideEffect

type SideEffect string
const (
	SideEffectRead           SideEffect = "read"
	SideEffectWrite          SideEffect = "write"
	SideEffectShell          SideEffect = "shell"
	SideEffectNetwork        SideEffect = "network"
	SideEffectLocalControl   SideEffect = "local_control"
	SideEffectLocalBrowser   SideEffect = "local_browser"
	SideEffectLocalDesktop   SideEffect = "local_desktop"
	SideEffectLocalTerminal  SideEffect = "local_terminal"
	SideEffectOutOfWorkspace SideEffect = "out_of_workspace"
	// SideEffectNone marks a control-only tool that performs no read/write/
	// shell/network effect (e.g. escalate_model). It must be recognized so it is
	// not normalized to out_of_workspace and falsely classified as critical.
	SideEffectNone SideEffect = "none"
)

func NormalizeSideEffect

func NormalizeSideEffect(value SideEffect) SideEffect

type StoreOptions

type StoreOptions struct {
	FilePath string
	Now      func() time.Time
	Env      map[string]string
}

type WSLInfo

type WSLInfo struct {
	IsWSL  bool
	IsWSL2 bool
	Kernel string
}

WSLInfo describes the Windows Subsystem for Linux environment, if any. It is derived from /proc/version.

type WindowsACLAction

type WindowsACLAction string
const (
	WindowsACLAllowWrite WindowsACLAction = "allow-write"
	WindowsACLDenyRead   WindowsACLAction = "deny-read"
	WindowsACLDenyWrite  WindowsACLAction = "deny-write"
)

type WindowsACLEntry

type WindowsACLEntry struct {
	Action      WindowsACLAction `json:"action"`
	Path        string           `json:"path"`
	Capability  string           `json:"capability"`
	Materialize bool             `json:"materialize,omitempty"`
}

type WindowsACLPlan

type WindowsACLPlan struct {
	Entries []WindowsACLEntry `json:"entries"`
}

func BuildWindowsACLPlan

func BuildWindowsACLPlan(config WindowsSandboxCommandConfig) (WindowsACLPlan, error)

type WindowsCapabilitySIDs

type WindowsCapabilitySIDs struct {
	SchemaVersion      int               `json:"schemaVersion"`
	ReadOnly           string            `json:"readOnly"`
	WorkspaceByRoot    map[string]string `json:"workspaceByRoot,omitempty"`
	WritableRootByPath map[string]string `json:"writableRootByPath,omitempty"`
	// Offline is a synthetic SID that carries NO filesystem ACL. The persistent
	// WFP outbound-block filter is scoped to it, so a command's network is gated
	// purely by whether its restricted token carries this SID: offline (deny)
	// commands include it and are blocked; online (approved) commands omit it and
	// reach the network — both still write-jailed by the capability SIDs.
	Offline string `json:"offline,omitempty"`
}

func LoadOrCreateWindowsCapabilitySIDs

func LoadOrCreateWindowsCapabilitySIDs(sandboxHome string) (WindowsCapabilitySIDs, error)

type WindowsNetworkPlan

type WindowsNetworkPlan struct {
	Mode         NetworkMode            `json:"mode"`
	ProviderKey  string                 `json:"providerKey,omitempty"`
	SubLayerKey  string                 `json:"subLayerKey,omitempty"`
	IdentitySIDs []string               `json:"identitySids,omitempty"`
	Filters      []WindowsWFPFilterSpec `json:"filters,omitempty"`
}

func BuildWindowsNetworkInfraPlan

func BuildWindowsNetworkInfraPlan(config WindowsSandboxCommandConfig) (WindowsNetworkPlan, error)

BuildWindowsNetworkInfraPlan returns the mode-INDEPENDENT network infrastructure that `zero sandbox setup` installs: the persistent outbound block filters scoped to the sandbox home's offline-marker SID. It is identical for allow and deny command configs — the per-command mode is enforced at runtime by whether the restricted token carries the offline-marker SID, not by which filters exist. This is what the setup marker fingerprints, so one setup validly serves both modes.

type WindowsSandboxCommandArgsOptions

type WindowsSandboxCommandArgsOptions struct {
	SandboxHome       string
	CommandCWD        string
	WorkspaceRoots    []string
	PermissionProfile PermissionProfile
	Env               []string
	SandboxLevel      WindowsSandboxLevel
	Command           []string
}

type WindowsSandboxCommandConfig

type WindowsSandboxCommandConfig struct {
	SandboxHome       string
	CommandCWD        string
	WorkspaceRoots    []string
	PermissionProfile PermissionProfile
	Env               map[string]string
	SandboxLevel      WindowsSandboxLevel
	Command           []string
}

func ParseWindowsSandboxCommandArgs

func ParseWindowsSandboxCommandArgs(args []string) (WindowsSandboxCommandConfig, error)

type WindowsSandboxHelper

type WindowsSandboxHelper struct {
	Name       string
	ArgsPrefix []string
}

WindowsSandboxHelper locates a Windows sandbox helper to launch. Name is the executable; ArgsPrefix is prepended to the helper's own arguments. For a standalone helper .exe (the release layout) ArgsPrefix is empty; for self-dispatch — the running zero binary acting as its own helper — Name is os.Executable() and ArgsPrefix carries the hidden subcommand token.

func ResolveWindowsSandboxCommandRunner

func ResolveWindowsSandboxCommandRunner(lookup func(string) (string, error)) WindowsSandboxHelper

ResolveWindowsSandboxCommandRunner locates the command-runner helper.

func ResolveWindowsSandboxSetupHelper

func ResolveWindowsSandboxSetupHelper(lookup func(string) (string, error)) WindowsSandboxHelper

ResolveWindowsSandboxSetupHelper locates the one-time setup helper.

func (WindowsSandboxHelper) Available

func (helper WindowsSandboxHelper) Available() bool

Available reports whether a helper executable was resolved.

type WindowsSandboxLevel

type WindowsSandboxLevel string
const (
	WindowsSandboxLevelRestrictedToken WindowsSandboxLevel = "restricted-token"
	// WindowsSandboxLevelUnelevated is the restricted-token tier without the
	// elevated setup: the runner applies the workspace ACL plan itself before
	// launching (no Administrator rights needed) and skips the elevated setup
	// marker check. Network is NOT enforced at this level — the WFP filters need
	// the elevated setup — so callers must keep network behind the approval gate.
	WindowsSandboxLevelUnelevated WindowsSandboxLevel = "unelevated"
	WindowsSandboxLevelElevated   WindowsSandboxLevel = "elevated"
	WindowsSandboxLevelDisabled   WindowsSandboxLevel = "disabled"
)

type WindowsSandboxSetupArgsOptions

type WindowsSandboxSetupArgsOptions struct {
	SandboxHome       string
	CommandCWD        string
	WorkspaceRoots    []string
	PermissionProfile PermissionProfile
}

type WindowsSandboxSetupConfig

type WindowsSandboxSetupConfig struct {
	SandboxHome       string
	CommandCWD        string
	WorkspaceRoots    []string
	PermissionProfile PermissionProfile
}

func ParseWindowsSandboxSetupArgs

func ParseWindowsSandboxSetupArgs(args []string) (WindowsSandboxSetupConfig, error)

func WindowsSandboxSetupConfigFromCommand

func WindowsSandboxSetupConfigFromCommand(config WindowsSandboxCommandConfig) WindowsSandboxSetupConfig

type WindowsSandboxSetupMarker

type WindowsSandboxSetupMarker struct {
	SchemaVersion  int    `json:"schemaVersion"`
	ACLPlanHash    string `json:"aclPlanHash"`
	ACLPlanEntries int    `json:"aclPlanEntries"`
	// NetworkInfraHash fingerprints the mode-INDEPENDENT network infrastructure
	// setup provisioned (block filters scoped to the offline-marker SID), so one
	// marker validly serves both an allow command and a deny command. It replaces
	// the old per-command NetworkPolicyHash/NetworkPlanHash, which locked the
	// marker to a single mode and bricked approved network commands.
	NetworkInfraHash string `json:"networkInfraHash"`
	OfflineFilterSID string `json:"offlineFilterSid"`
	NetworkFilters   int    `json:"networkFilters"`
}

func BuildWindowsSandboxSetupMarker

func BuildWindowsSandboxSetupMarker(config WindowsSandboxSetupConfig) (WindowsSandboxSetupMarker, error)

func WriteWindowsSandboxSetupMarker

func WriteWindowsSandboxSetupMarker(config WindowsSandboxSetupConfig) (WindowsSandboxSetupMarker, error)

type WindowsUnelevatedAppliedPlan added in v0.2.0

type WindowsUnelevatedAppliedPlan struct {
	ACLPlanHash    string `json:"aclPlanHash"`
	ACLPlanEntries int    `json:"aclPlanEntries"`
}

WindowsUnelevatedAppliedPlan fingerprints one workspace ACL plan the unelevated tier has applied. Unlike the elevated setup marker it carries no network infrastructure hash: the unelevated tier never provisions WFP filters, so there is nothing network-side to fingerprint.

type WindowsUnelevatedSetupMarker added in v0.2.0

type WindowsUnelevatedSetupMarker struct {
	SchemaVersion int                            `json:"schemaVersion"`
	AppliedPlans  []WindowsUnelevatedAppliedPlan `json:"appliedPlans,omitempty"`
}

WindowsUnelevatedSetupMarker records which workspace ACL plans the command runner has applied without elevation, keyed by plan hash, so repeat commands in a known workspace skip the re-apply. One file serves every workspace under a sandbox home (the elevated marker is instead a single-plan snapshot, because its WFP half genuinely is machine-global).

type WindowsWFPConditionSpec

type WindowsWFPConditionSpec struct {
	Kind  string `json:"kind"`
	Value uint16 `json:"value,omitempty"`
}

type WindowsWFPFilterSpec

type WindowsWFPFilterSpec struct {
	Key         string                    `json:"key"`
	Name        string                    `json:"name"`
	Description string                    `json:"description,omitempty"`
	Layer       string                    `json:"layer"`
	Action      string                    `json:"action"`
	Conditions  []WindowsWFPConditionSpec `json:"conditions,omitempty"`
}

type WritableRoot

type WritableRoot struct {
	Root                   string   `json:"root"`
	ReadOnlySubpaths       []string `json:"readOnlySubpaths,omitempty"`
	ProtectedMetadataNames []string `json:"protectedMetadataNames,omitempty"`
}

Jump to

Keyboard shortcuts

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