classifier

package
v1.12.1 Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
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

View Source
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

func CategorizeToolName(name string) string

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

type ClassificationContext struct {
	Cwd        string
	IsGitRepo  bool
	RepoRoot   string
	IsWorktree bool
}

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 RiskLevel

type RiskLevel int

RiskLevel indicates the severity of a tool use request.

const (
	RiskLow RiskLevel = iota
	RiskMedium
	RiskHigh
	RiskCritical
)

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

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.

Jump to

Keyboard shortcuts

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