danger

package
v0.16.6 Latest Latest
Warning

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

Go to latest
Published: May 20, 2026 License: MIT Imports: 5 Imported by: 0

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.

const (
	Allow  Action = "allow"
	Prompt Action = "prompt"
	Deny   Action = "deny"
)

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.

const (
	Safe          RiskClass = "safe"
	LocalWrite    RiskClass = "local_write"
	SystemWrite   RiskClass = "system_write"
	Destructive   RiskClass = "destructive"
	NetworkEgress RiskClass = "network_egress"
	CodeExecution RiskClass = "code_execution"
	Install       RiskClass = "install"
	Blocked       RiskClass = "blocked"
)

func Classify

func Classify(cmd string) RiskClass

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

func ClassifyPath(path string) RiskClass

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

func ClassifyURL(rawURL string) RiskClass

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

type ToolOperation struct {
	Name     string
	Resource string
	Risk     RiskClass
}

ToolOperation describes a native tool call for approval checking.

Jump to

Keyboard shortcuts

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