Documentation
¶
Overview ¶
Package risk provides a rule-based engine for detecting dangerous SQL patterns by inspecting the AST produced by the CockroachDB parser.
The engine is organized around three concepts:
- Rule: a named check that inspects a single parsed statement and returns zero or more findings. Each rule has a severity, reason code, and category.
- Registry: an ordered collection of rules. Its Analyze method parses a SQL string and runs every rule against every statement.
- Finding: a single risk detected in a SQL statement, carrying a machine-readable reason code, human-readable message, position within the input, and a fix hint.
Callers that want the built-in rule set can use the package-level Analyze function, which delegates to DefaultRules().
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CheckInput ¶
CheckInput is the context passed to a rule's check function for a single parsed statement.
type Finding ¶
type Finding struct {
ReasonCode string `json:"reason_code"`
Severity Severity `json:"severity"`
Message string `json:"message"`
Position *Position `json:"position,omitempty"`
FixHint string `json:"fix_hint"`
}
Finding is a single risk detected by a rule. The struct is the JSON-serializable shape embedded in both the CLI envelope's Data field and the MCP tool result.
func Analyze ¶
Analyze is a convenience function that runs the default rule set against sql. It is equivalent to NewRegistry(DefaultRules(), DefaultMultiRules()).Analyze(sql).
func AnalyzeParsed ¶
func AnalyzeParsed(stmts statements.Statements, sql string) []Finding
AnalyzeParsed is a convenience function that runs the default rule set against already-parsed statements. It is equivalent to NewRegistry(DefaultRules(), DefaultMultiRules()).AnalyzeParsed(stmts, sql).
type MultiCheckInput ¶
type MultiCheckInput struct {
Stmts statements.Statements
Positions []Position
}
MultiCheckInput is the context passed to a multi-statement rule's check function. Stmts is the full parsed statement list for the SQL passed to Analyze; Positions[i] is the location of Stmts[i] within the original SQL. The two slices have the same length and are indexed in parallel.
type MultiRule ¶
type MultiRule struct {
ReasonCode string
Severity Severity
Category string
Check func(input MultiCheckInput) []Finding
}
MultiRule defines a risk detection rule that needs to look across more than one parsed statement at a time (e.g. spotting multiple DDL statements inside a single explicit BEGIN..COMMIT block). The Check function is invoked once per Analyze call with the full statement list and returns any findings; it is expected to return nil when the input does not contain anything relevant.
func DefaultMultiRules ¶
func DefaultMultiRules() []MultiRule
DefaultMultiRules returns the built-in set of AST-only risk rules that need to look across more than one parsed statement at a time.
type Position ¶
type Position struct {
Line int `json:"line"`
Column int `json:"column"`
ByteOffset int `json:"byte_offset"`
}
Position identifies a location within the original SQL input. Line and Column are 1-based; ByteOffset is 0-based.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds an ordered set of per-statement rules and an ordered set of multi-statement rules, and runs them against parsed SQL. Built by NewRegistry and immutable afterward; rule evaluation order matches the order provided to the constructor (per-statement rules run first, in registration order, for each statement; multi-rules run afterward, in registration order, once per Analyze call).
func NewRegistry ¶
NewRegistry creates a registry from the given per-statement rules and multi-statement rules. Either slice may be nil. Rules are evaluated in the order provided: per-statement rules in registration order for each statement, then multi-statement rules in registration order once per Analyze call. It panics if any rule has a nil Check function, an empty ReasonCode, or a ReasonCode that duplicates any other registered rule (across both slices).
func (*Registry) Analyze ¶
Analyze parses sql and applies every registered rule. Per-statement rules run first, in statement order, with rules evaluated in registration order within each statement; multi-statement rules run afterward, in registration order, each invoked once over the full statement list. Findings are returned in production order, so all per-statement findings precede all multi-statement findings. The registry stamps each finding's ReasonCode and Severity from the rule that produced it, so individual rules only need to set Message, Position, and FixHint.
func (*Registry) AnalyzeParsed ¶
func (r *Registry) AnalyzeParsed(stmts statements.Statements, sql string) []Finding
AnalyzeParsed runs every registered rule against already-parsed statements. sql is the original source text — required for positionFromSQL to locate each statement's line/column. Exposed so callers that already invoked parser.Parse (e.g. to also run version.Inspect on the same AST) can reuse the parsed output rather than reparsing. Returns no error: parsing happened upstream.
type Rule ¶
type Rule struct {
ReasonCode string
Severity Severity
Category string
Check func(input CheckInput) []Finding
}
Rule defines an AST-only risk detection rule. The Check function inspects a single parsed statement and returns any findings. Rules are expected to return nil when the statement is not relevant (e.g. a DELETE rule receiving a SELECT AST).
func DefaultRules ¶
func DefaultRules() []Rule
DefaultRules returns the built-in set of AST-only risk rules that inspect a single statement at a time.