Class: LanguageOperator::Agent::Safety::ASTValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/language_operator/agent/safety/ast_validator.rb

Overview

Validates synthesized Ruby code for security before execution Performs static analysis to detect dangerous method calls

Supports DSL v1 (task/main model) and validates both neural and symbolic task implementations to ensure they use only safe Ruby subset.

Defined Under Namespace

Classes: SecurityError

Constant Summary collapse

ALLOWED_REQUIRES =

Gems that are safe to require (allowlist) These are required for agent execution and are safe

%w[
  language_operator
].freeze
DANGEROUS_METHODS =

Dangerous methods that should never be called in synthesized code

%w[
  system exec spawn fork ` eval instance_eval class_eval module_eval
  require load autoload require_relative
  send __send__ public_send method __method__
  const_set const_get remove_const
  define_method define_singleton_method
  undef_method remove_method alias_method
  exit exit! abort throw
  trap at_exit
  open
].freeze
DANGEROUS_CONSTANTS =

Dangerous constants that should not be accessed

%w[
  File Dir IO FileUtils Pathname
  Process Kernel ObjectSpace GC
  Thread Fiber Mutex ConditionVariable
  Socket TCPSocket UDPSocket TCPServer UDPServer
  STDIN STDOUT STDERR
].freeze
SAFE_AGENT_METHODS =

Safe DSL methods that are allowed in agent definitions (DSL v1)

%w[
  agent description persona schedule objectives objective
  task main execute_task inputs outputs instructions
  constraints budget max_requests rate_limit content_filter
  output mode webhook as_mcp_server as_chat_endpoint
].freeze
SAFE_TOOL_METHODS =

Safe DSL methods for tool definitions

%w[
  tool description parameter type required default
  execute
].freeze
SAFE_HELPER_METHODS =

Safe helper methods available in execute blocks

%w[
  HTTP Shell
  validate_url validate_phone validate_email
  env_required env_get
  truncate parse_csv
  error success
  TypeCoercion
].freeze
SAFE_BUILTINS =

Safe Ruby built-in methods and classes

%w[
  String Array Hash Integer Float Symbol
  puts print p pp warn
  true false nil
  if unless case when then else elsif end
  while until for break next redo retry return
  begin rescue ensure
  lambda proc block_given? yield
  attr_reader attr_writer attr_accessor
  private protected public
  initialize new
].freeze

Instance Method Summary collapse

Constructor Details

#initializeASTValidator

Returns a new instance of ASTValidator.



82
83
84
# File 'lib/language_operator/agent/safety/ast_validator.rb', line 82

def initialize
  # Prism doesn't require initialization
end

Instance Method Details

#validate(code, file_path = '(eval)') ⇒ Array<Hash>

Validate code and return array of violations (non-raising version)

Parameters:

  • code (String)

    Ruby code to validate

  • file_path (String) (defaults to: '(eval)')

    Path to file (for error messages)

Returns:

  • (Array<Hash>)

    Array of violation hashes



105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/language_operator/agent/safety/ast_validator.rb', line 105

def validate(code, file_path = '(eval)')
  begin
    ast = parse_code(code, file_path)
  rescue SecurityError => e
    # Convert SecurityError (which wraps syntax error) to violation
    return [{ type: :syntax_error, message: e.message }]
  end

  return [] if ast.nil?

  scan_ast(ast)
rescue Prism::ParseError => e
  [{ type: :syntax_error, message: e.message }]
end

#validate!(code, file_path = '(eval)') ⇒ Object

Validate code and raise SecurityError if dangerous methods found

Parameters:

  • code (String)

    Ruby code to validate

  • file_path (String) (defaults to: '(eval)')

    Path to file (for error messages)

Raises:



90
91
92
93
94
95
96
97
98
99
# File 'lib/language_operator/agent/safety/ast_validator.rb', line 90

def validate!(code, file_path = '(eval)')
  ast = parse_code(code, file_path)
  return if ast.nil? # Empty code is safe

  violations = scan_ast(ast)

  return if violations.empty?

  raise SecurityError, format_violations(violations, file_path)
end