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
// 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 handles pipelines (|), sequential commands (;, &&, ||), environment variable prefixes, path-qualified program names (/usr/bin/git), and sudo/exec wrappers.
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.