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
1) The unsafe version
def unsafe_call(llm_generated_code)
eval(llm_generated_code)
end
2) The Ruby Box version
def safe_call(llm_generated_code)
box = Ruby::Box.new
box.eval(llm_generated_code)
end
Test the Code
1) 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"
)
2) 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
3) Run the test
puts "unsafe_call"
unsafe_call(llm_malicious_code)
puts "safe_call"
safe_call(llm_malicious_code)
4) 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
1) 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.
2) Currently, the feature is not recommended to be used in production, as it has several known issues and bugs.