Documentation
¶
Overview ¶
Package danger classifies shell commands by risk level and provides a configurable approval system for dangerous operations.
Classification is token-based (not regex) — it respects quotes, pipes, redirects, compound commands (&&, ||, ;), and multi-line input. Each command is classified into one of 8 risk classes, and the user can configure which actions (allow/prompt/deny) apply to each class.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Action ¶
type Action string
Action represents what to do when a command of a given risk class is detected.
type Approver ¶
type Approver interface {
// PromptCommand asks the user to approve or deny a shell command.
// cls is the risk class (system_write, network_egress, etc.).
// Returns nil on approve, error on deny or timeout.
PromptCommand(cls RiskClass, cmd, description string) error
// PromptOperation asks the user to approve or deny a native tool operation
// (read_file on /etc, browser to external URL, etc.).
PromptOperation(op ToolOperation) error
}
Approver is the interface for user approval of dangerous operations. Two implementations exist:
- TTYApprover — opens /dev/tty for interactive approval (CLI mode)
- WSApprover — sends approval requests via WebSocket (serve mode)
When nil (no approver configured), calls fall back to non-interactive behavior (NonInteractiveAction). Tools MUST inject an approver to get interactive approval in any mode.
type DangerousConfig ¶
type DangerousConfig struct {
// Classes maps risk classes to their configured action.
// Only overrides for non-default values need to be set.
Classes map[RiskClass]Action `json:"classes,omitempty"`
// Allowlist is a list of command strings that are always allowed,
// regardless of their risk classification. Exact match only.
// Takes priority over Denylist.
Allowlist []string `json:"allowlist,omitempty"`
// Denylist is a list of command strings that are always denied,
// regardless of their risk classification. Exact match only.
Denylist []string `json:"denylist,omitempty"`
// DefaultAction is used when no /dev/tty is available (non-interactive mode).
// Values: "allow" (default), "deny", "prompt"
// "prompt" in non-interactive mode falls back to "allow".
DefaultAction *string `json:"action,omitempty"`
// NonInteractive specifies what to do when running without a TTY.
// "allow" (default) — run everything, "deny" — block all prompted ops.
NonInteractive *string `json:"non_interactive,omitempty"`
// Approver handles interactive approval prompts for dangerous operations.
// When set, all Prompt-class operations use this instead of /dev/tty.
// Tools can inject their own approver (e.g., WebSocket-based for odek serve).
// When nil, CheckOperation falls back to /dev/tty (CLI-compatible default).
Approver Approver `json:"-"`
}
DangerousConfig defines how dangerous operations are handled. Configurable via the standard 4-layer odek config chain.
Default behavior per class (no sandbox):
safe → allow, local_write → allow, system_write → prompt, destructive → deny, network_egress → prompt, code_execution → prompt, install → prompt, blocked → deny
func (*DangerousConfig) ActionFor ¶
func (c *DangerousConfig) ActionFor(cls RiskClass) Action
ActionFor returns the configured action for the given risk class. Falls back to defaults for unknown classes and unconfigured classes.
func (*DangerousConfig) ActionForCommand ¶
func (c *DangerousConfig) ActionForCommand(cmd string) Action
ActionForCommand returns the action for a specific command string. Allowlist and denylist are checked first (exact match), then falls back to the risk-class-based action.
func (*DangerousConfig) CheckOperation ¶
func (c *DangerousConfig) CheckOperation(op ToolOperation, trustedClasses map[RiskClass]bool) error
CheckOperation checks whether a tool operation is allowed, denied, or needs approval. Returns nil on allow, error on deny, and prompts the user on prompt. Uses the configured Approver when set; falls back to /dev/tty (TTYApprover) when no approver is configured.
func (*DangerousConfig) NonInteractiveAction ¶
func (c *DangerousConfig) NonInteractiveAction() Action
NonInteractiveAction returns the action to use when no TTY is available.
type RiskClass ¶
type RiskClass string
RiskClass represents the risk level of a shell command.
func Classify ¶
Classify determines the risk class of a shell command using token-level heuristics. Returns the highest-severity class detected.
Priority (highest to lowest): blocked > destructive > system_write > code_execution > network_egress > install > local_write > safe
func ClassifyPath ¶
ClassifyPath returns a RiskClass for a filesystem path. /tmp/*, working directory → local_write; /etc/*, /root/* → system_write; /boot/*, /dev/*, /sys/* → destructive; home sensitive dirs → system_write.
func ClassifyURL ¶
ClassifyURL returns a RiskClass for a browser URL. Internal IPs → system_write; external → network_egress.
type TTYApprover ¶
type TTYApprover struct {
DangerousConfig *DangerousConfig
TrustedClasses map[RiskClass]bool
TTYPath string // overridden in tests
}
TTYApprover implements Approver by reading from /dev/tty. This is the default approver used in CLI mode (odek run, odek repl). When /dev/tty is not available (piped stdin, CI), it falls back to the configured NonInteractiveAction.
func NewTTYApprover ¶
func NewTTYApprover(cfg *DangerousConfig) *TTYApprover
NewTTYApprover creates a TTYApprover with the given config.
func (*TTYApprover) PromptCommand ¶
func (a *TTYApprover) PromptCommand(cls RiskClass, cmd, description string) error
func (*TTYApprover) PromptOperation ¶
func (a *TTYApprover) PromptOperation(op ToolOperation) error
type ToolOperation ¶
ToolOperation describes a native tool call for approval checking.