Documentation
¶
Index ¶
- Constants
- Variables
- func CategorizeToolName(name string) string
- type ClassificationContext
- type ClassificationDecision
- type ClassificationResult
- type Classifier
- type CommandCriteria
- type CommandInfo
- type ParsedCommand
- type PermissionRequestPayload
- type PythonInfo
- type RiskLevel
- type Rule
- type RuleBasedClassifier
- func (c *RuleBasedClassifier) AddRules(rules []Rule)
- func (c *RuleBasedClassifier) BuildContext(cwd string) ClassificationContext
- func (c *RuleBasedClassifier) Classify(payload PermissionRequestPayload, ctx ClassificationContext) ClassificationResult
- func (c *RuleBasedClassifier) ReplaceRules(rules []Rule)
- func (c *RuleBasedClassifier) Rules() []Rule
- type SecurityFinding
Constants ¶
const ( // ToolCategoryAny matches any tool (empty string — default behaviour). ToolCategoryAny = "" // ToolCategoryBuiltin matches any Claude Code built-in tool (no "__" in name). // Examples: Bash, Read, Write, Edit, Glob, Grep, Task, WebFetch, WebSearch, ToolSearch. ToolCategoryBuiltin = "builtin" // ToolCategoryBuiltinAgent matches planning / task-management built-ins that pose no risk. // Examples: ExitPlanMode, EnterPlanMode, AskUserQuestion, TodoWrite, Task*, Skill, NotebookEdit. ToolCategoryBuiltinAgent = "builtin-agent" // ToolCategoryMCP matches any MCP tool (name contains "__"). ToolCategoryMCP = "mcp" // ToolCategoryMCPRead matches MCP tools whose operation names are read-only. // Determined by CategorizeToolName; covers context7, sequential-thinking, and // filesystem/repomix read operations. ToolCategoryMCPRead = "mcp-read" // ToolCategoryMCPWrite matches MCP tools whose operation names mutate state. ToolCategoryMCPWrite = "mcp-write" )
ToolCategory constants classify tool names into coarse groups for use in Rule.ToolCategory. This lets seed rules match whole classes of tools without fragile long regex patterns.
Variables ¶
var PythonPrograms = map[string]bool{ "python": true, "python3": true, "python2": true, "pypy": true, "pypy3": true, }
PythonPrograms is the set of program names that invoke a Python interpreter.
Functions ¶
func CategorizeToolName ¶
CategorizeToolName returns the ToolCategory constant for a given tool name. The classification uses Claude Code naming conventions:
- MCP tools follow the pattern "mcp__<server>__<operation>" (contains "__").
- Built-in tools never contain "__".
- Agent tools are a named subset of built-ins.
Types ¶
type ClassificationContext ¶
ClassificationContext provides local-environment context to the classifier.
type ClassificationDecision ¶
type ClassificationDecision int
ClassificationDecision is the action taken by the classifier.
const ( // AutoAllow bypasses the manual review queue and immediately allows the request. AutoAllow ClassificationDecision = iota // AutoDeny immediately denies the request, optionally suggesting an alternative. AutoDeny // Escalate sends the request to the manual review queue for human review. Escalate )
type ClassificationResult ¶
type ClassificationResult struct {
Decision ClassificationDecision
RiskLevel RiskLevel
Reason string
Alternative string
RuleID string
RuleName string
}
ClassificationResult holds the outcome of classifying a tool use request.
type Classifier ¶
type Classifier interface {
Classify(payload PermissionRequestPayload, ctx ClassificationContext) ClassificationResult
BuildContext(cwd string) ClassificationContext
}
Classifier classifies a PermissionRequestPayload to determine the action to take.
type CommandCriteria ¶
type CommandCriteria struct {
// Programs lists the allowed primary programs. Empty means any program matches.
// Prefix matching handles versioned interpreters (e.g., "python3" matches "python3.11").
Programs []string
// Subcommands lists allowed subcommand values. Empty means any (or no) subcommand matches.
// For deep-subcommand programs (gh, aws, etc.) multi-word entries are supported ("pr view").
Subcommands []string
// BlockedSubcommands lists subcommands that prevent this rule from matching.
BlockedSubcommands []string
// RequiredFlags: at least one of the listed flags must be present in the command args.
// Uses exact token matching (e.g., RequiredFlags: ["--hard"] matches git reset --hard only).
RequiredFlags []string
// RequiredFlagPrefixes: like RequiredFlags but uses prefix matching.
// Useful when a flag accepts an optional inline value (e.g., sed -i.bak satisfies prefix "-i").
RequiredFlagPrefixes []string
// ForbiddenFlags: if any of these flags appear in args, the rule does not match.
ForbiddenFlags []string
// PythonModes restricts matching to specific Python invocation modes.
// Valid values: "inline" (-c), "module" (-m), "version" (-V/--version), "script" (*.py).
// Empty means no Python-mode check is performed.
PythonModes []string
// SafePythonImportsOnly restricts inline Python (-c) matches to commands whose
// import statements use only known-safe stdlib modules (see safeStdlibModules).
// When true the rule will not match if any import is outside the safelist, or if
// the invocation is not inline. Combine with PythonModes: ["inline"].
SafePythonImportsOnly bool
// RedirectionPattern matches against any file paths targeted by shell redirections.
RedirectionPattern *regexp.Regexp
}
CommandCriteria provides structured, composable matching criteria for Bash commands. It is evaluated against a ParsedCommand and allows precise rules without complex regex. When multiple fields are set, all must match (AND semantics).
func (*CommandCriteria) Matches ¶
func (cc *CommandCriteria) Matches(pc ParsedCommand) bool
Matches returns true if pc satisfies all criteria fields.
type CommandInfo ¶
type CommandInfo struct {
// Program is the primary executable being invoked (first non-env-var, non-wrapper token).
Program string
// Subcommand is the first positional argument after the program, if it looks like a
// subcommand (i.e., does not start with '-').
Subcommand string
// Category classifies Program into a high-level category (e.g., "vcs", "runtime").
Category string
// AllPrograms contains all distinct programs found across the full command line,
// including across pipes, semicolons, and logical operators.
AllPrograms []string
}
CommandInfo contains parsed information extracted from a Bash command string.
func ParseBashCommand ¶
func ParseBashCommand(command string) CommandInfo
ParseBashCommand extracts structured categorization information from a Bash command. It uses the mvdan.cc/sh AST parser (via ExtractAllCommands) as the primary path, which correctly handles subshells, pipelines, compound commands, and env-var prefixes. On parse error, ExtractAllCommands falls back to splitCommandParts automatically.
The primary program and subcommand are taken from the first CallExpr in the AST. AllPrograms collects all distinct programs across the full command.
type ParsedCommand ¶
type ParsedCommand struct {
// Program is the primary executable (path-stripped).
Program string
// Args is the list of remaining tokens.
Args []string
// Raw is the reconstructed "program arg1 arg2 …" string for pattern matching.
Raw string
// Redirections lists the targets of any shell redirections (e.g., "> file", ">> file").
Redirections []string
}
ParsedCommand is a single simple command extracted from a (potentially compound) shell command.
func ExtractAllCommands ¶
func ExtractAllCommands(cmd string) []ParsedCommand
ExtractAllCommands parses cmd with mvdan.cc/sh and recursively walks the AST, returning all CallExpr nodes — including those inside $(), backticks, and process substitutions. Falls back to splitCommandParts() on parse error.
type PermissionRequestPayload ¶
type PermissionRequestPayload struct {
SessionID string `json:"session_id"`
TranscriptPath string `json:"transcript_path"`
Cwd string `json:"cwd"`
PermissionMode string `json:"permission_mode"`
HookEventName string `json:"hook_event_name"`
ToolName string `json:"tool_name"`
ToolInput map[string]interface{} `json:"tool_input"`
}
PermissionRequestPayload is the JSON payload from Claude Code's PermissionRequest HTTP hook.
type PythonInfo ¶
type PythonInfo struct {
// Imports contains top-level module names imported in inline Python code.
// Only populated when -c is used (inline code), not for script files.
Imports []string
// IsInline is true when code was passed via the -c flag.
IsInline bool
}
PythonInfo contains information extracted from a Python command invocation.
func ParsePythonCommand ¶
func ParsePythonCommand(command string) PythonInfo
ParsePythonCommand extracts Python import information from a python/python3 invocation. Only parses inline code passed via the -c flag; script files are not read.
type Rule ¶
type Rule struct {
ID string
Name string
// ToolName is an exact match on the tool name (case-insensitive). If non-empty, ToolPattern is ignored.
ToolName string
// ToolPattern matches against the tool name when ToolName is empty.
ToolPattern *regexp.Regexp
// ToolCategory matches against the structural category returned by CategorizeToolName.
// Evaluated after ToolName/ToolPattern (those take precedence when non-empty).
// Use one of the ToolCategory* constants. Empty string means any category matches.
ToolCategory string
// Criteria provides structured matching for Bash command programs, subcommands and flags.
// When set alongside CommandPattern, both must match (AND semantics).
Criteria *CommandCriteria
// CommandPattern matches against tool_input["command"]. nil means any command matches.
CommandPattern *regexp.Regexp
// FilePattern matches against tool_input["file_path"]. nil means any file path matches.
FilePattern *regexp.Regexp
Decision ClassificationDecision
RiskLevel RiskLevel
Reason string
Alternative string
// Priority determines rule evaluation order. Higher values are evaluated first.
Priority int
Enabled bool
// Source tracks how the rule was loaded: "seed", "user", or "claude-settings".
Source string
}
Rule is a single classification rule evaluated against a tool use request.
func SeedRules ¶
func SeedRules() []Rule
SeedRules returns the built-in rule set, sorted by Priority descending. Priority tiers:
1000 — AutoDeny (critical, must fire before any allow) 500 — Escalate-before-allow (targeted escalations that override allow rules at 100) 100 — AutoAllow (standard development operations) 50 — Escalate catch-all (operations with no allow rule; provides a helpful reason)
Criteria-based rules provide precise matching without complex regex; CommandPattern is retained only where regex expressiveness is needed.
type RuleBasedClassifier ¶
type RuleBasedClassifier struct {
// contains filtered or unexported fields
}
RuleBasedClassifier evaluates a priority-ordered list of Rules.
func NewRuleBasedClassifier ¶
func NewRuleBasedClassifier() *RuleBasedClassifier
NewRuleBasedClassifier creates a classifier pre-loaded with seed rules.
func (*RuleBasedClassifier) AddRules ¶
func (c *RuleBasedClassifier) AddRules(rules []Rule)
AddRules appends additional rules and re-sorts by priority.
func (*RuleBasedClassifier) BuildContext ¶
func (c *RuleBasedClassifier) BuildContext(cwd string) ClassificationContext
BuildContext detects git repository state for the given working directory.
func (*RuleBasedClassifier) Classify ¶
func (c *RuleBasedClassifier) Classify(payload PermissionRequestPayload, ctx ClassificationContext) ClassificationResult
Classify evaluates rules in priority order and returns the first match. For Bash commands, compound commands (with &&, |, ;, $(), etc.) are evaluated using classifyCompound to ensure every sub-command is covered. If no rule matches, returns Escalate for human review.
func (*RuleBasedClassifier) ReplaceRules ¶
func (c *RuleBasedClassifier) ReplaceRules(rules []Rule)
ReplaceRules atomically replaces all rules with the provided list.
func (*RuleBasedClassifier) Rules ¶
func (c *RuleBasedClassifier) Rules() []Rule
Rules returns a copy of the current rule set.
type SecurityFinding ¶
type SecurityFinding struct {
ID string
Name string
RiskLevel RiskLevel
Reason string
Alternative string
}
SecurityFinding represents a potential security risk discovered during deep AST analysis.
func AuditCommand ¶
func AuditCommand(cmd string, cwd string) []SecurityFinding
AuditCommand performs deep AST analysis on a shell command to identify dangerous patterns.