safety

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

Package safety provides safety gate functionality for the agent loop.

The safety gate validates proposed changes before they are executed, checking for potential issues like dangerous patterns, sensitive file modifications, or security vulnerabilities.

Thread Safety:

All types in this package are designed for concurrent use.

Index

Constants

View Source
const SafetyBlockedError = "blocked by safety check"

SafetyBlockedError is the error string prefix for safety-blocked operations.

Variables

This section is empty.

Functions

func IsSafetyError

func IsSafetyError(errMsg string) bool

IsSafetyError returns true if the error message indicates a safety violation.

Description:

Detects if an error was caused by the safety gate blocking an operation.
This allows the CDCL algorithm to classify safety violations as hard
signals and learn to avoid patterns that trigger safety blocks.

Inputs:

errMsg - The error message to check.

Outputs:

bool - True if this is a safety violation error.

Types

type ChangeMetadata

type ChangeMetadata struct {
	// Reason explains why this change is being made.
	Reason string `json:"reason,omitempty"`

	// ToolName is the tool that initiated this change.
	ToolName string `json:"tool_name,omitempty"`

	// InvocationID links to the tool invocation.
	InvocationID string `json:"invocation_id,omitempty"`

	// OldContent is the previous content (for modifications).
	OldContent string `json:"old_content,omitempty"`

	// LineRange specifies the affected lines (for partial edits).
	LineRange *LineRange `json:"line_range,omitempty"`

	// Permissions are the requested file permissions (for creates).
	Permissions string `json:"permissions,omitempty"`
}

ChangeMetadata contains additional typed information about a proposed change.

type Checker

type Checker interface {
	// Name returns the checker name.
	Name() string

	// Check runs the safety check.
	Check(ctx context.Context, change *ProposedChange) []Issue
}

Checker is a single safety check.

type CommandChecker

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

CommandChecker validates shell commands against blocked patterns.

Description:

Checks if proposed shell commands contain blocked patterns
defined in the configuration (e.g., "rm -rf", "chmod 777").
Returns critical issues for any blocked command matches.

Thread Safety:

CommandChecker is safe for concurrent use as it only reads config.

func (*CommandChecker) Check

func (c *CommandChecker) Check(ctx context.Context, change *ProposedChange) []Issue

Check implements Checker.

func (*CommandChecker) Name

func (c *CommandChecker) Name() string

Name implements Checker.

type DefaultGate

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

DefaultGate implements the Gate interface with configurable checks.

Thread Safety: DefaultGate is safe for concurrent use.

func NewDefaultGate

func NewDefaultGate(config *GateConfig) *DefaultGate

NewDefaultGate creates a new safety gate with the provided config.

Description:

Creates a DefaultGate instance with the specified configuration.
Registers default checkers: PathChecker, CommandChecker, and FileSizeChecker.
If config is nil, uses DefaultGateConfig().

Inputs:

config - Gate configuration. If nil, uses defaults.

Outputs:

*DefaultGate - The configured gate with default checkers registered.

Example:

gate := NewDefaultGate(&GateConfig{
    Enabled:         true,
    BlockOnCritical: true,
    BlockedPaths:    []string{".git", ".env"},
})

func (*DefaultGate) Check

func (g *DefaultGate) Check(ctx context.Context, changes []ProposedChange) (*Result, error)

Check implements Gate.

func (*DefaultGate) GenerateWarnings

func (g *DefaultGate) GenerateWarnings(result *Result) []string

GenerateWarnings implements Gate.

func (*DefaultGate) RegisterChecker

func (g *DefaultGate) RegisterChecker(checker Checker)

RegisterChecker adds a checker to the gate.

func (*DefaultGate) ShouldBlock

func (g *DefaultGate) ShouldBlock(result *Result) bool

ShouldBlock implements Gate.

type FileSizeChecker

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

FileSizeChecker validates file write sizes against configured limits.

Description:

Checks if proposed file write content exceeds the maximum file size
limit defined in the configuration. Returns a warning for oversized files.

Thread Safety:

FileSizeChecker is safe for concurrent use as it only reads config.

func (*FileSizeChecker) Check

func (c *FileSizeChecker) Check(ctx context.Context, change *ProposedChange) []Issue

Check implements Checker.

func (*FileSizeChecker) Name

func (c *FileSizeChecker) Name() string

Name implements Checker.

type Gate

type Gate interface {
	// Check validates the proposed changes.
	//
	// Inputs:
	//   ctx - Context for cancellation.
	//   changes - The changes to validate.
	//
	// Outputs:
	//   *Result - The check result.
	//   error - Non-nil if the check itself fails.
	Check(ctx context.Context, changes []ProposedChange) (*Result, error)

	// ShouldBlock determines if the result should block execution.
	//
	// Inputs:
	//   result - The check result.
	//
	// Outputs:
	//   bool - True if execution should be blocked.
	ShouldBlock(result *Result) bool

	// GenerateWarnings creates human-readable warnings from issues.
	//
	// Inputs:
	//   result - The check result.
	//
	// Outputs:
	//   []string - Warning messages.
	GenerateWarnings(result *Result) []string
}

Gate is the safety gate interface.

Implementations validate proposed changes before execution.

type GateConfig

type GateConfig struct {
	// Enabled determines if safety checks are enabled.
	Enabled bool

	// BlockOnCritical determines if critical issues block execution.
	BlockOnCritical bool

	// BlockOnWarning determines if warnings also block execution.
	BlockOnWarning bool

	// AllowedPaths are paths that are always allowed to be modified.
	AllowedPaths []string

	// BlockedPaths are paths that are never allowed to be modified.
	BlockedPaths []string

	// AllowedCommands are shell commands that are always allowed.
	AllowedCommands []string

	// BlockedCommands are shell commands that are never allowed.
	BlockedCommands []string

	// MaxFileSize is the maximum allowed file size for writes.
	MaxFileSize int64

	// AllowPackageInstall permits package installation commands when true.
	// When false (default), commands like "npm install", "pip install",
	// "cargo install", etc. are blocked to prevent supply chain attacks.
	// Set to true only when explicitly requested by user (e.g., --allow-install flag).
	AllowPackageInstall bool
}

GateConfig configures the safety gate behavior.

func DefaultGateConfig

func DefaultGateConfig() GateConfig

DefaultGateConfig returns sensible defaults.

type Issue

type Issue struct {
	// Severity indicates how serious the issue is.
	Severity Severity `json:"severity"`

	// Code is a machine-readable issue code.
	Code string `json:"code"`

	// Message is a human-readable description.
	Message string `json:"message"`

	// Change is the change that triggered this issue.
	Change *ProposedChange `json:"change,omitempty"`

	// Suggestion is an optional suggested fix.
	Suggestion string `json:"suggestion,omitempty"`
}

Issue represents a safety issue found during checking.

type LineRange

type LineRange struct {
	Start int `json:"start"`
	End   int `json:"end"`
}

LineRange specifies a range of lines in a file.

type MockGate

type MockGate struct {

	// CheckFunc overrides Check behavior.
	CheckFunc func(ctx context.Context, changes []ProposedChange) (*Result, error)

	// ShouldBlockFunc overrides ShouldBlock behavior.
	ShouldBlockFunc func(result *Result) bool

	// Calls records all Check calls.
	Calls [][]ProposedChange
	// contains filtered or unexported fields
}

MockGate is a mock implementation for testing.

func NewMockGate

func NewMockGate() *MockGate

NewMockGate creates a new mock gate.

func (*MockGate) CallCount

func (m *MockGate) CallCount() int

CallCount returns the number of Check calls.

func (*MockGate) Check

func (m *MockGate) Check(ctx context.Context, changes []ProposedChange) (*Result, error)

Check implements Gate.

func (*MockGate) GenerateWarnings

func (m *MockGate) GenerateWarnings(result *Result) []string

GenerateWarnings implements Gate.

func (*MockGate) Reset

func (m *MockGate) Reset()

Reset clears all recorded calls.

func (*MockGate) ShouldBlock

func (m *MockGate) ShouldBlock(result *Result) bool

ShouldBlock implements Gate.

type PathChecker

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

PathChecker validates file operations against blocked path patterns.

Description:

Checks if proposed file operations (writes, deletes) target paths
that match blocked patterns defined in the configuration.
Returns critical issues for any blocked path matches.

Thread Safety:

PathChecker is safe for concurrent use as it only reads config.

func (*PathChecker) Check

func (c *PathChecker) Check(ctx context.Context, change *ProposedChange) []Issue

Check implements Checker.

func (*PathChecker) Name

func (c *PathChecker) Name() string

Name implements Checker.

type ProposedChange

type ProposedChange struct {
	// Type is the kind of change (e.g., "file_write", "file_delete", "shell_command").
	Type string `json:"type"`

	// Target is the target of the change (e.g., file path, command).
	Target string `json:"target"`

	// Content is the proposed content (for writes).
	Content string `json:"content,omitempty"`

	// Metadata contains additional typed information about the change.
	Metadata *ChangeMetadata `json:"metadata,omitempty"`
}

ProposedChange represents a change the agent wants to make.

type Result

type Result struct {
	// Passed is true if no blocking issues were found.
	Passed bool `json:"passed"`

	// Issues contains all issues found during checking.
	Issues []Issue `json:"issues,omitempty"`

	// CriticalCount is the number of critical issues.
	CriticalCount int `json:"critical_count"`

	// WarningCount is the number of warnings.
	WarningCount int `json:"warning_count"`

	// ChecksRun is the number of safety checks that were executed.
	ChecksRun int `json:"checks_run"`
}

Result contains the result of a safety check.

func (*Result) HasCritical

func (r *Result) HasCritical() bool

HasCritical returns true if there are critical issues.

func (*Result) HasWarnings

func (r *Result) HasWarnings() bool

HasWarnings returns true if there are warnings.

func (*Result) ToErrorMessage

func (r *Result) ToErrorMessage() string

ToErrorMessage converts a Result to an error message for learning.

Description:

Creates a detailed error message from safety issues that can be used
by CDCL for conflict analysis. The message includes issue codes for
pattern matching.

Inputs:

result - The safety check result.

Outputs:

string - The error message for learning.

type SafetyConstraint

type SafetyConstraint struct {
	// IssueCode is the safety issue code (e.g., "SUPPLY_CHAIN_INSTALL").
	IssueCode string

	// Pattern describes what triggered the violation.
	Pattern string

	// ConflictingNodes are the MCTS nodes involved in the violation.
	ConflictingNodes []string

	// Reason explains why this is blocked.
	Reason string
}

SafetyConstraint represents a constraint derived from a safety violation.

This is used to feed safety violations to CDCL as learning signals. When the safety gate blocks an action, the constraint encodes what pattern should be avoided.

func ExtractConstraints

func ExtractConstraints(result *Result, nodeID string) []SafetyConstraint

ExtractConstraints extracts learning constraints from safety issues.

Description:

Converts safety issues into constraints that CDCL can learn from.
Each constraint encodes a pattern that should be avoided in future
search iterations.

Inputs:

result - The safety check result containing issues.
nodeID - The MCTS node ID that triggered the check.

Outputs:

[]SafetyConstraint - Constraints derived from the issues.

type Severity

type Severity string

Severity indicates the severity of a safety issue.

const (
	// SeverityInfo is for informational messages.
	SeverityInfo Severity = "info"

	// SeverityWarning is for warnings that should be reviewed.
	SeverityWarning Severity = "warning"

	// SeverityCritical is for critical issues that should block execution.
	SeverityCritical Severity = "critical"
)

type SupplyChainChecker

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

SupplyChainChecker validates shell commands against supply chain attack patterns.

Description:

Blocks package manager installation commands that could introduce malicious
dependencies. Commands like "npm install", "pip install", "cargo install"
are blocked by default because postinstall scripts can execute arbitrary code.
Safe subcommands (test, build, run) are always allowed.

Thread Safety:

SupplyChainChecker is safe for concurrent use as it only reads config.

func (*SupplyChainChecker) Check

func (c *SupplyChainChecker) Check(ctx context.Context, change *ProposedChange) []Issue

Check implements Checker.

Description:

Validates shell commands against supply chain attack patterns.
Blocks package installation commands unless AllowPackageInstall is set.

Inputs:

ctx - Context for cancellation (unused but required by interface).
change - The proposed change to validate.

Outputs:

[]Issue - List of issues found. Empty if command is allowed.

func (*SupplyChainChecker) Name

func (c *SupplyChainChecker) Name() string

Name implements Checker.

Jump to

Keyboard shortcuts

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