Documentation
¶
Overview ¶
Package lockdown holds the run-level taint state of the opt-in untrusted-content lockdown (untrusted_content.enabled / --lockdown, issue #171). A run becomes tainted when content from an untrusted source enters the model's context (a web_fetch or MCP result, a review diff, an --untrusted-task task). From then until the run ends the outbound channels tinyagent controls are refused: commands, web_fetch outside its lockdown allowlist, and MCP tools.
Taint is decided by source, never by content, and records hold only source names, tool names, ids, steps and hosts: no fetched content, MCP results, URLs, query strings or environment values.
Index ¶
- Constants
- Variables
- func ParseSources(list []string) (map[string]bool, error)
- func RefusalMessage(tool, channel string, first Source, host string) string
- func URLHostPort(raw string) (host string, port int, ok bool)
- type Denial
- type MCPServerPolicy
- type Source
- type State
- func (s *State) ACPClientMCPAliases() []string
- func (s *State) CommandDomains() []string
- func (s *State) CommandsConfined() bool
- func (s *State) CommandsInfo() map[string]any
- func (s *State) ConfineCommands(proxied bool, narrow func([]string))
- func (s *State) ContainerProxy() bool
- func (s *State) Denials() []Denial
- func (s *State) Deny(d Denial)
- func (s *State) Describe() string
- func (s *State) EnabledSources() []string
- func (s *State) First() (src Source, ok bool)
- func (s *State) Info() map[string]any
- func (s *State) MCPAliases() []string
- func (s *State) MCPCallAllowed(aliases []string) bool
- func (s *State) MCPCallTaints(aliases []string) bool
- func (s *State) MCPTaintSource(aliases []string) (string, bool)
- func (s *State) RefuseCommands()
- func (s *State) Restore(sources []Source, denials []Denial)
- func (s *State) SetACPClientMCPServers(aliases []string)
- func (s *State) SetCommandAllowedDomains(domains []string) error
- func (s *State) SetCommandsDirectUntilTaint()
- func (s *State) SetCommandsInContainer(removedAtTaint bool)
- func (s *State) SetContainerProxy(on bool)
- func (s *State) SetMCPServers(servers []MCPServerPolicy)
- func (s *State) SetSources(list []string) error
- func (s *State) Sources() []Source
- func (s *State) StopsProcessesAtTaint() bool
- func (s *State) Taint(src Source) (added, first bool)
- func (s *State) Tainted() bool
- func (s *State) TaintsFrom(source string) bool
- func (s *State) WebFetchAllowed(host string, port int) bool
- func (s *State) WebFetchDomains() []string
- func (s *State) WebFetchGate(host string, port int) error
Constants ¶
const ( // CommandsRefused: commands are refused after taint. CommandsRefused = "refused" // CommandsSandboxed: commands keep running after taint, confined by the // sandbox. CommandsSandboxed = "sandboxed" // CommandNetworkDenied: confined commands have no network. CommandNetworkDenied = "denied" // CommandNetworkProxy: confined commands reach the network only through // the allowlist proxy, narrowed at the first taint. CommandNetworkProxy = "proxy" )
Command policy values reported in run.started and OTel attributes.
const ( SourceWebFetch = "web_fetch" SourceMCP = "mcp" SourceReview = "review" SourceUntrustedTask = "untrusted_task" // SourceResume marks a resumed checkpoint whose history already holds // untrusted content. SourceResume = "resume" )
Taint sources.
const ( ChannelCommand = "command" ChannelWebFetch = "web_fetch" ChannelMCP = "mcp" )
Channels lockdown restricts after taint.
const CommandEnvironmentContainer = "container"
CommandEnvironmentContainer is the environment value reported in run.started for commands confined in the container environment.
const CommandNetworkDirect = "direct"
CommandNetworkDirect is run.started's lockdown.commands.network_before_taint when sandboxed commands have direct network (sandbox_network) until the first taint takes it away.
const Notice = "[tinyagent: untrusted content received; commands, web_fetch and MCP tools are restricted for the rest of this run]"
Notice is appended once per run to the tool result that first taints it.
const SourceACPClientMCP = "acp_client_mcp"
SourceACPClientMCP is a result from an MCP server an ACP client supplied to the session (see SetACPClientMCPServers).
Variables ¶
var ConfigurableSources = []string{SourceWebFetch, SourceMCP, SourceReview, SourceACPClientMCP}
ConfigurableSources are the taint sources untrusted_content.sources can choose from, in the order they are described. --untrusted-task and a resumed untrusted checkpoint are not configurable: asking for them is explicit, and a tainted history stays tainted.
Functions ¶
func ParseSources ¶
ParseSources checks an untrusted_content.sources list and returns the enabled set. A nil list (the key is absent) enables every configurable source and returns nil. An explicit empty list, an unknown name and a duplicate are errors, so a typo can't silently turn a source off.
func RefusalMessage ¶
RefusalMessage is the tool error the model sees for a refused call.
Types ¶
type Denial ¶
type Denial struct {
Channel string `json:"channel"`
Tool string `json:"tool"`
ToolCallID string `json:"tool_call_id"`
Step int `json:"step"`
Host string `json:"host,omitempty"`
}
Denial is one call refused by lockdown.
type MCPServerPolicy ¶
type MCPServerPolicy struct {
Alias string
// Trusted is untrusted: false: the server's results don't taint the
// run. The default is false, so results taint.
Trusted bool
// LockdownAllowed is lockdown_allowed: true: the server's tools stay
// callable after taint. The default is false, so they are refused.
LockdownAllowed bool
}
MCPServerPolicy is one configured MCP server's lockdown settings (mcp_servers[].untrusted and mcp_servers[].lockdown_allowed).
type Source ¶
type Source struct {
Source string `json:"source"`
Step int `json:"step"`
ToolCallID string `json:"tool_call_id,omitempty"`
Tool string `json:"tool,omitempty"`
// Host is the web_fetch URL host (no scheme, path or query).
Host string `json:"host,omitempty"`
// Resumed marks a source restored from a checkpoint: it tainted an
// earlier invocation of the run.
Resumed bool `json:"resumed,omitempty"`
}
Source is one recorded taint: what brought untrusted content into context and where.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is one run's lockdown state. It is shared by the run's agent and its children (workers, delegates), so it is safe for concurrent use. A nil *State means lockdown is off: it is never tainted and refuses nothing.
func New ¶
New returns an untainted state whose web_fetch lockdown allowlist is webFetchAllowed, in the sandbox_allowed_domains syntax.
func (*State) ACPClientMCPAliases ¶
ACPClientMCPAliases returns the client-supplied server aliases, sorted.
func (*State) CommandDomains ¶
CommandDomains returns untrusted_content.lockdown.allowed_domains.
func (*State) CommandsConfined ¶
CommandsConfined reports whether commands keep running after taint.
func (*State) CommandsInfo ¶
CommandsInfo returns the after-taint command policy for run.started: policy (refused or sandboxed), and for sandboxed commands their network (denied or proxy). Proxied commands also list allowed_domains, the untrusted_content.lockdown.allowed_domains patterns the proxy is narrowed to at taint ([] when none). Host patterns only, never content.
func (*State) ConfineCommands ¶
ConfineCommands marks the run's commands as confined, so they keep running after taint instead of being refused. proxied says they reach the network only through the allowlist proxy; narrow, which may be nil when they have no network, restricts that proxy to CommandDomains. narrow runs once: at the first taint, or right away when the run is already tainted. Call it only when every command the run can start (workers included) goes through that sandbox, and before the run starts.
func (*State) ContainerProxy ¶
ContainerProxy reports untrusted_content.lockdown.container_proxy.
func (*State) EnabledSources ¶
EnabledSources lists the configurable sources that taint the run, in ConfigurableSources order.
func (*State) Info ¶
Info returns the lockdown config, the after-taint command policy (see CommandsInfo) and the current taint state for run.started: names and host patterns only, never content.
func (*State) MCPAliases ¶
MCPAliases returns the aliases of the servers SetMCPServers and SetACPClientMCPServers recorded, in sorted order.
func (*State) MCPCallAllowed ¶
MCPCallAllowed reports whether a call that may reach any of aliases is still allowed after taint. It fails closed: an empty list or an unknown alias is refused, and every server must be lockdown_allowed: true.
func (*State) MCPCallTaints ¶
MCPCallTaints reports whether a result from a call that may have reached any of aliases taints the run. It fails closed: an empty list or an unknown alias taints, and so does any server not marked untrusted: false.
func (*State) MCPTaintSource ¶
MCPTaintSource returns the taint source of a result from a call that may have reached any of aliases, and whether it taints the run. A client-supplied server taints as acp_client_mcp, any other server not marked untrusted: false as mcp; the first such server whose source is enabled in untrusted_content.sources decides. It fails closed: a call that can't be tied to a server (empty aliases) taints as mcp, or as acp_client_mcp when mcp is turned off and the client supplied servers.
func (*State) RefuseCommands ¶
func (s *State) RefuseCommands()
RefuseCommands withdraws ConfineCommands: commands are refused after taint from now on. It is the fail-closed path when the narrow hook can't restrict their network.
func (*State) Restore ¶
Restore records the taint sources and denials of a resumed checkpoint ahead of any recorded so far, so a run that was tainted stays tainted with its original sources. The sources are marked Resumed, and the first-taint notice counts as given: the conversation already carries it. Call it before the run starts.
func (*State) SetACPClientMCPServers ¶
SetACPClientMCPServers marks the run as an ACP session and records the aliases of the MCP servers its client supplied. Results from those servers taint as acp_client_mcp rather than mcp, so untrusted_content.sources can choose them separately. Client servers have no mcp_servers entry, so they keep the strict defaults: their results always taint (when acp_client_mcp is a source) and their tools are refused after taint. Call it before the session's first turn.
func (*State) SetCommandAllowedDomains ¶
SetCommandAllowedDomains records untrusted_content.lockdown.allowed_domains, the hosts sandboxed commands may still reach through the allowlist proxy after taint (sandbox_allowed_domains syntax; a bare * is rejected). Call it before the run starts.
func (*State) SetCommandsDirectUntilTaint ¶
func (s *State) SetCommandsDirectUntilTaint()
SetCommandsDirectUntilTaint records that the confined commands (ConfineCommands) have direct network until the first taint, when the narrow hook takes it away: a sandbox_network sandbox. Background processes started before taint keep their direct network, so StopsProcessesAtTaint reports true. Call it after ConfineCommands and before the run starts.
func (*State) SetCommandsInContainer ¶
SetCommandsInContainer records that the confined commands (ConfineCommands) run in the container environment. removedAtTaint says the container has network until the first taint, when the narrow hook disconnects it; otherwise it never had any (--network none). Processes running in the container lose their network with it, so background processes are left running. Call it after ConfineCommands and before the run starts.
func (*State) SetContainerProxy ¶
SetContainerProxy records untrusted_content.lockdown.container_proxy: in the container environment, commands reach CommandDomains after taint through a lockdown proxy on an internal runtime network instead of having no network. Call it before the run starts.
func (*State) SetMCPServers ¶
func (s *State) SetMCPServers(servers []MCPServerPolicy)
SetMCPServers records the configured MCP servers' lockdown settings. Call it before the run starts. A server that isn't listed, including one an ACP client supplies, keeps the defaults: its results taint and its tools are refused after taint.
func (*State) SetSources ¶
SetSources limits the configurable sources that taint the run to list, in the untrusted_content.sources syntax (nil means all of them). Call it before the run starts.
func (*State) StopsProcessesAtTaint ¶
StopsProcessesAtTaint reports whether the first taint must stop the running background processes because lockdown can't restrict their network: commands aren't confined, or had direct network until taint.
func (*State) Taint ¶
Taint records src. added is false when the same source, tool and host were already recorded, or when src's source is turned off in untrusted_content.sources. first is true only for the run's first taint, the one whose tool result carries Notice; a taint recorded before the run starts (task, review, resume) has no result and uses it up, since every refusal explains itself anyway.
func (*State) TaintsFrom ¶
TaintsFrom reports whether a result from source taints the run. It is always false when lockdown is off, and always true for the sources that aren't configurable (an untrusted task, a resumed untrusted checkpoint).
func (*State) WebFetchAllowed ¶
WebFetchAllowed reports whether web_fetch may still read host:port: always before taint, and after taint only when it matches the lockdown allowlist.
func (*State) WebFetchDomains ¶
WebFetchDomains returns the configured web_fetch lockdown allowlist.