Ruby 4.0.0 has an experimental feature - Ruby Box. It provides in-process isolation for Ruby code execution, by creating a separated spaces within a single Ruby process, preventing code in one box from affecting another or the main application. This article shows a simple use case of the new feature.
Scenario
You are supplying a tool for LLM to execute a piece of Ruby code it generated and return the results of the execution.
The Code
-
The unsafe version
def unsafe_call(llm_generated_code) eval(llm_generated_code) end -
The Ruby Box version
def safe_call(llm_generated_code) box = Ruby::Box.new box.eval(llm_generated_code) end
Test the Code
-
Pretend we have a global current_user, like so:
class User attr_accessor :id, :email, :password_hash, :api_key, :role def initialize(id:, email:, password_hash:, api_key:, role:) @id = id @email = email @password_hash = password_hash @api_key = api_key @role = role end end $current_user = User.new( id: 42, email: "admin@company.com", password_hash: "$2a$12$K8pQXvZ8...", api_key: "sk_live_abc123xyz789secretkey", role: "admin" ) -
Consider the following code provided by LLM:
llm_malicious_code = <<'RUBY' result = 2 + 2 stolen_data = { user_id: $current_user.instance_variable_get(:@id), email: $current_user.instance_variable_get(:@email), password_hash: $current_user.instance_variable_get(:@password_hash), api_key: $current_user.instance_variable_get(:@api_key), role: $current_user.instance_variable_get(:@role) } stolen_data.each { |k, v| puts " #{k}: #{v}" } result RUBY -
Run the test
puts "unsafe_call" unsafe_call(llm_malicious_code) puts "safe_call" safe_call(llm_malicious_code) -
And we can observe the result - The unsafe version has a credential leaked.
ruby: warning: Ruby::Box is experimental, and the behavior may change in the future! See https://docs.ruby-lang.org/en/4.0/Ruby/Box.html for known issues, etc. unsafe_call user_id: 42 email: admin@company.com password_hash: $2a$12$K8pQXvZ8... api_key: sk_live_abc123xyz789secretkey role: admin safe_call user_id: email: password_hash: api_key: role:
Notes
-
The Ruby box demonstrates a strong potential in many use cases, including potentially a safer LLM function-calling environment. Although additional security measures are still required, such as providing a whitelist to "require" and detecting malicious patterns in code.
-
Currently, the feature is not recommended to be used in production, as it has several known issues and bugs.