Class: LanguageOperator::Agent::Safety::SafeExecutor::SandboxProxy

Inherits:
BasicObject
Defined in:
lib/language_operator/agent/safety/safe_executor.rb

Overview

Proxy class that wraps the context and intercepts method calls

Instance Method Summary collapse

Constructor Details

#initialize(context, executor) ⇒ SandboxProxy

Returns a new instance of SandboxProxy.



78
79
80
81
# File 'lib/language_operator/agent/safety/safe_executor.rb', line 78

def initialize(context, executor)
  @__context__ = context
  @__executor__ = executor
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ Object

Delegate method calls to the underlying context but check for dangerous methods first



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/language_operator/agent/safety/safe_executor.rb', line 85

def method_missing(method_name, *args, &)
  # Log the call
  @__executor__.log_call(@__context__, method_name, args)

  # Special handling for require - allow only 'language_operator'
  if %i[require require_relative].include?(method_name)
    required_gem = args.first.to_s
    return ::Kernel.require(required_gem) if required_gem == 'language_operator'

    # Allow require 'language_operator'

    ::Kernel.raise ::LanguageOperator::Agent::Safety::SafeExecutor::SecurityError,
                   "Require '#{required_gem}' is not allowed. Only 'require \"language_operator\"' is permitted."

  end

  # Check if method is safe
  unless safe_method?(method_name)
    ::Kernel.raise ::LanguageOperator::Agent::Safety::SafeExecutor::SecurityError,
                   "Method '#{method_name}' is not allowed in sandboxed code"
  end

  # Delegate to underlying context
  @__context__.send(method_name, *args, &)
end

Instance Method Details

#const_missing(name) ⇒ Object

Provide access to safe constants from the context



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/language_operator/agent/safety/safe_executor.rb', line 116

def const_missing(name)
  # Define allowed constants explicitly (security-by-default)
  # This allowlist must be kept in sync with ASTValidator safe constants
  case name
  when :HTTP
    ::LanguageOperator::Dsl::HTTP
  when :Shell
    ::LanguageOperator::Dsl::Shell
  when :String, :Array, :Hash, :Integer, :Float, :Numeric, :Symbol
    # Allow safe Ruby built-in types
    ::Object.const_get(name)
  when :Time, :Date
    # Allow safe time/date types
    ::Object.const_get(name)
  when :TrueClass, :FalseClass, :NilClass
    # Allow boolean and nil types
    ::Object.const_get(name)
  when :ArgumentError, :TypeError, :RuntimeError, :StandardError
    # Allow standard Ruby exception classes for error handling
    ::Object.const_get(name)
  else
    # Security-by-default: explicitly deny access to any other constants
    # This prevents sandbox bypass through const_missing fallback
    ::Kernel.raise ::LanguageOperator::Agent::Safety::SafeExecutor::SecurityError,
                   "Access to constant '#{name}' is not allowed in sandbox (security restriction)"
  end
end

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/language_operator/agent/safety/safe_executor.rb', line 111

def respond_to_missing?(method_name, include_private = false)
  @__context__.respond_to?(method_name, include_private)
end