policy

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 24, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package policy provides bash command security checking.

Package policy provides security policy loading and enforcement.

Index

Constants

This section is empty.

Variables

View Source
var BannedCommands = []string{

	"alias",
	"aria2c",
	"axel",
	"chrome",
	"curl",
	"curlie",
	"firefox",
	"http-prompt",
	"httpie",
	"links",
	"lynx",
	"nc",
	"netcat",
	"ncat",
	"safari",
	"scp",
	"sftp",
	"ssh",
	"telnet",
	"w3m",
	"wget",
	"xh",

	"doas",
	"su",
	"sudo",
	"pkexec",
	"gksudo",
	"kdesudo",

	"apk",
	"apt",
	"apt-cache",
	"apt-get",
	"dnf",
	"dpkg",
	"emerge",
	"home-manager",
	"makepkg",
	"opkg",
	"pacman",
	"paru",
	"pkg",
	"pkg_add",
	"pkg_delete",
	"portage",
	"rpm",
	"yay",
	"yum",
	"zypper",
	"snap",
	"flatpak",
	"nix-env",

	"at",
	"batch",
	"chkconfig",
	"crontab",
	"fdisk",
	"mkfs",
	"mount",
	"parted",
	"service",
	"systemctl",
	"umount",
	"shutdown",
	"reboot",
	"poweroff",
	"init",
	"telinit",

	"firewall-cmd",
	"ifconfig",
	"ip",
	"iptables",
	"ip6tables",
	"nft",
	"netstat",
	"pfctl",
	"route",
	"ufw",
	"nmcli",
	"networkctl",

	"useradd",
	"userdel",
	"usermod",
	"groupadd",
	"groupdel",
	"groupmod",
	"passwd",
	"chpasswd",
	"adduser",
	"deluser",

	"shred",
	"wipe",
	"dd",
	"losetup",

	"setcap",
	"getcap",
	"chroot",
	"unshare",
	"nsenter",
}

BannedCommands is the hardcoded list of commands that are always blocked. These are dangerous for system security and should never be executed by an agent. Based on Charmbracelet Crush's approach.

View Source
var BannedSubcommandPatterns = []BannedSubcommand{

	{Command: "apk", Args: []string{"add"}},
	{Command: "apt", Args: []string{"install"}},
	{Command: "apt-get", Args: []string{"install"}},
	{Command: "dnf", Args: []string{"install"}},
	{Command: "pacman", Flags: []string{"-S"}},
	{Command: "pkg", Args: []string{"install"}},
	{Command: "yum", Args: []string{"install"}},
	{Command: "zypper", Args: []string{"install"}},

	{Command: "brew", Args: []string{"install"}},
	{Command: "cargo", Args: []string{"install"}},
	{Command: "gem", Args: []string{"install"}},
	{Command: "go", Args: []string{"install"}},
	{Command: "npm", Args: []string{"install"}, Flags: []string{"--global", "-g"}},
	{Command: "pip", Args: []string{"install"}, Flags: []string{"--user", "--system"}},
	{Command: "pip3", Args: []string{"install"}, Flags: []string{"--user", "--system"}},
	{Command: "pnpm", Args: []string{"add"}, Flags: []string{"--global", "-g"}},
	{Command: "yarn", Args: []string{"global", "add"}},

	{Command: "go", Args: []string{"test"}, Flags: []string{"-exec"}},

	{Command: "git", Args: []string{"config", "--global"}},
	{Command: "git", Args: []string{"config", "--system"}},

	{Command: "docker", Args: []string{"run"}, Flags: []string{"--privileged"}},
	{Command: "docker", Args: []string{"run"}, Flags: []string{"-v", "/:/"}},
	{Command: "podman", Args: []string{"run"}, Flags: []string{"--privileged"}},
}

BannedSubcommandPatterns blocks specific subcommand patterns even if the base command is allowed.

View Source
var DangerousPipePatterns = []*regexp.Regexp{
	regexp.MustCompile(`(?i)curl\s+.+\|\s*(ba)?sh`),
	regexp.MustCompile(`(?i)wget\s+.+\|\s*(ba)?sh`),
	regexp.MustCompile(`(?i)curl\s+.+\|\s*python`),
	regexp.MustCompile(`(?i)wget\s+.+\|\s*python`),
	regexp.MustCompile(`(?i)\|\s*sudo\b`),
	regexp.MustCompile(`(?i)\|\s*su\b`),
	regexp.MustCompile(`(?i)\|\s*base64\s+-d\s*\|\s*(ba)?sh`),
}

DangerousPipePatterns detects dangerous command chaining.

View Source
var ProtectedFiles = []string{
	"agent.toml",
	"credentials.toml",
	"policy.toml",
}

ProtectedFiles are files that agents cannot modify (security-critical).

Functions

func MergeUserDenylist

func MergeUserDenylist(userDenied []string) []string

MergeUserDenylist merges user-defined denied commands with the built-in list, returning the combined set (with duplicates removed).

Types

type BannedSubcommand

type BannedSubcommand struct {
	Command string
	Args    []string // Subcommand arguments (e.g., ["install"])
	Flags   []string // Flags that trigger block (e.g., ["--global", "-g"])
}

BannedSubcommands defines specific subcommand patterns to block. Format: command, subcommand args, flags (any of which triggers block)

type BashCheckResult

type BashCheckResult struct {
	Allowed      bool
	Reason       string
	InputTokens  int
	OutputTokens int
}

BashCheckResult contains the result of a bash command check.

type BashChecker

type BashChecker struct {
	// AllowedDirs from agent.toml - directories the agent can access
	AllowedDirs []string

	// UserDeniedCommands from agent.toml - additional commands to block
	UserDeniedCommands []string

	// LLMChecker is called for step 2 (semantic check) if step 1 passes
	// Takes: command string, allowed_dirs []string
	// Returns: (*BashCheckResult, error)
	LLMChecker func(ctx context.Context, command string, allowedDirs []string) (*BashCheckResult, error)

	// Workspace is the base working directory
	Workspace string

	// OnDecision is called after each security decision for logging/auditing.
	// step: "deterministic" or "llm"
	// allowed: whether the command was allowed
	// reason: explanation (especially for blocks)
	// durationMs: time taken for the check (0 for deterministic, >0 for LLM)
	// inputTokens, outputTokens: token counts (0 for deterministic)
	OnDecision func(command, step string, allowed bool, reason string, durationMs int64, inputTokens, outputTokens int)
}

BashChecker provides two-step bash command security checking.

func NewBashChecker

func NewBashChecker(workspace string, allowedDirs, userDeniedCommands []string) *BashChecker

NewBashChecker creates a new bash security checker.

func (*BashChecker) Check

func (c *BashChecker) Check(ctx context.Context, command string) (bool, string, error)

Check performs two-step security checking on a bash command. Step 1: Deterministic denylist check (fast, zero LLM cost) Step 2: LLM policy check (only if step 1 passes and LLMChecker is configured)

func (*BashChecker) CheckDeterministic

func (c *BashChecker) CheckDeterministic(command string) (bool, string)

CheckDeterministic performs only the fast deterministic checks (for testing/preview).

func (*BashChecker) SetLLMChecker

func (c *BashChecker) SetLLMChecker(checker LLMPolicyChecker)

SetLLMChecker sets the LLM checker for directory policy verification.

type GenerateResult

type GenerateResult struct {
	Content      string
	InputTokens  int
	OutputTokens int
}

GenerateResult contains the LLM response with token counts.

type LLMPolicyChecker

type LLMPolicyChecker interface {
	// CheckBashCommand asks the LLM if a bash command violates directory policy.
	// Returns (*BashCheckResult, error)
	CheckBashCommand(ctx context.Context, command string, allowedDirs []string) (*BashCheckResult, error)
}

LLMPolicyChecker is an interface for LLM-based policy checking.

type LLMProvider

type LLMProvider interface {
	// Generate returns the LLM's response to a prompt with token counts.
	Generate(ctx context.Context, prompt string) (*GenerateResult, error)
}

LLMProvider is the minimal interface needed for policy checking.

type MCPPolicy

type MCPPolicy struct {
	// DefaultDeny: if true, all MCP tools are blocked unless in AllowedTools.
	// If false, all MCP tools are allowed (dev mode).
	// If not set (nil MCPPolicy), logs a security warning.
	DefaultDeny  bool
	AllowedTools []string // List of "server:tool" patterns to allow
}

MCPPolicy controls MCP tool access.

type Policy

type Policy struct {
	DefaultDeny bool
	Workspace   string
	HomeDir     string
	ConfigDir   string // Directory containing agent.toml, policy.toml
	Tools       map[string]*ToolPolicy
	MCP         *MCPPolicy      // MCP tools policy
	Security    *SecurityPolicy // Security patterns and keywords
}

Policy represents the security policy for the agent.

func LoadFile

func LoadFile(path string) (*Policy, error)

LoadFile loads a policy from a TOML file.

func New

func New() *Policy

New creates a new policy with defaults.

func NewRestrictive

func NewRestrictive() *Policy

NewRestrictive creates a restrictive policy that denies everything by default.

func Parse

func Parse(content string) (*Policy, error)

Parse parses a policy from TOML content.

func (*Policy) CheckCommand

func (p *Policy) CheckCommand(tool, cmd string) (bool, string)

CheckCommand checks if a command is allowed for bash.

func (*Policy) CheckDomain

func (p *Policy) CheckDomain(tool, domain string) (bool, string)

CheckDomain checks if a domain is allowed for web tools.

func (*Policy) CheckMCPTool

func (p *Policy) CheckMCPTool(server, tool string) (bool, string, string)

CheckMCPTool checks if an MCP tool is allowed. Returns (allowed, reason, warning). Warning is non-empty if MCP policy is not configured (security issue).

func (*Policy) CheckPath

func (p *Policy) CheckPath(tool, path string) (bool, string)

CheckPath checks if a path is allowed for a tool.

func (*Policy) GetToolPolicy

func (p *Policy) GetToolPolicy(tool string) *ToolPolicy

GetToolPolicy returns the policy for a tool, with defaults.

func (*Policy) IsProtectedFile

func (p *Policy) IsProtectedFile(path string) bool

IsProtectedFile checks if a path refers to a protected config file. Protected files cannot be modified by the agent. Resolves symlinks to prevent bypass attacks.

func (*Policy) IsToolEnabled

func (p *Policy) IsToolEnabled(tool string) bool

IsToolEnabled checks if a tool is enabled.

type SecurityPolicy

type SecurityPolicy struct {
	// ExtraPatterns are additional regex patterns to detect (on top of built-ins)
	// Format: "name:regex" e.g., "exfil_attempt:send.*to.*external"
	ExtraPatterns []string
	// ExtraKeywords are additional sensitive keywords to detect (on top of built-ins)
	ExtraKeywords []string
}

SecurityPolicy contains custom patterns and keywords for content scanning.

type SmallLLMChecker

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

SmallLLMChecker implements LLMPolicyChecker using a fast/cheap LLM.

func NewSmallLLMChecker

func NewSmallLLMChecker(provider LLMProvider) *SmallLLMChecker

NewSmallLLMChecker creates a new LLM-based policy checker.

func (*SmallLLMChecker) CheckBashCommand

func (c *SmallLLMChecker) CheckBashCommand(ctx context.Context, command string, allowedDirs []string) (*BashCheckResult, error)

CheckBashCommand asks the LLM if a bash command violates directory policy. Returns a BashCheckResult with the decision and token usage.

func (*SmallLLMChecker) SetSecurityScope

func (c *SmallLLMChecker) SetSecurityScope(scope string)

SetSecurityScope sets the security research scope for exception handling. When set, the LLM is told about authorized security research activities.

type ToolPolicy

type ToolPolicy struct {
	Enabled      bool
	Allow        []string
	Deny         []string
	Allowlist    []string // for bash: legacy command allowlist
	Denylist     []string // for bash: additional commands to block
	AllowedDirs  []string // for bash: directories agent can access
	AllowDomains []string // for web tools
	RateLimit    int      // requests per minute
	Sandbox      string   // for bash: "none", "bwrap", "docker" (default: none)
}

ToolPolicy represents the policy for a specific tool.

Jump to

Keyboard shortcuts

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