đ Contents
- what is eval
- Why You Should Avoid eval
- Security Risks of Using eval
- Safe Alternatives to eval
- Real-World Example
- How eval Interacts with Rails Controllers and Models
- Benchmarking: eval vs. send vs. method_missing in Rails
- Safe String Interpolation vs. eval in Dynamic Code
- Behind the Scenes
- Examples
- Interview Questions and Answers
- Best Practices
đ Understanding eval in Ruby: What It Is and How It Works
In Ruby, the eval method is used to evaluate a string as Ruby code at runtime. This allows developers to write highly dynamic and flexible code that can adapt based on conditions during execution.
For example, you can pass a string like \"2 + 2\" to eval, and it will return the result of that expressionâ4. This makes eval incredibly powerful, but also potentially dangerous when used with untrusted input.
Common use cases include:
- Evaluating dynamic formulas in admin panels
- Building internal scripting tools
- Constructing DSLs (Domain-Specific Languages)
- Debugging and meta-programming tasks
However, eval should be used with extreme caution. Executing arbitrary strings as code can lead to serious security vulnerabilities such as remote code execution, data leaks, and file system access.
eval on raw user input. Always validate, sanitize, or use safer alternatives like send, case/when, or parsing libraries such as Dentaku.đŤ Why You Should Avoid eval in Rails Apps
While eval can dynamically execute Ruby code, it poses significant risksâespecially in web applications like those built with Rails. Using eval on untrusted input opens up your application to severe security vulnerabilities.
Common dangers include:
- Remote Code Execution (RCE): An attacker could inject and run arbitrary Ruby code.
- Access to Sensitive Data:
evalcan access environment variables, database credentials, and more. - File System Access: Malicious input can delete or modify files on the server.
- Hard to Debug: Debugging eval-related bugs is extremely difficult due to dynamic execution.
- Slower Performance: Code evaluated with
evalbypasses some Ruby optimizations.
Even in trusted admin panels, using eval should be avoided unless absolutely necessaryâand even then, only with rigorous input validation and sandboxing techniques.
eval can be replaced with safer alternatives like send, case statements, or expression parsers such as Dentaku.đ Security Risks of Using eval in Rails
The eval method can be incredibly dangerous in a Rails application if not used with absolute caution. When it executes user-supplied input, it essentially gives the user the ability to run arbitrary Ruby code on your serverâturning a small mistake into a critical vulnerability.
Common security risks of using eval include:
- Remote Code Execution (RCE): Attackers can inject and execute malicious Ruby code.
- Data Breaches: Sensitive data like user records, tokens, or credentials can be accessed and exfiltrated.
- Privilege Escalation: If roles are improperly checked, an attacker might gain admin access through code injection.
- File System Attacks: Attackers can read, write, or delete files using Ruby I/O methods like
File.openorFile.delete. - DoS (Denial of Service): Infinite loops or heavy operations inside
evalcan crash your app or exhaust resources.
Even if input seems safe (like mathematical formulas), attackers can sneak in harmful code using Ruby methods. There is no reliable way to sanitize arbitrary Ruby strings without removing all flexibility.
eval(params[:user_input]) or anything similar. Never trust user inputâeven from internal usersâunless strictly validated.â
Safe Alternatives to eval in Rails
Instead of using eval to dynamically run code, Ruby and Rails provide safer and more structured alternatives. These options allow dynamic behavior without the security risks.
1. send and public_send
Use send to call methods dynamically. public_send is saferâit wonât call private methods.
class User
def greet
"Hello!"
end
end
method = "greet"
user = User.new
puts user.public_send(method) # => "Hello!"2. define_method for Dynamic Methods
Dynamically define methods at runtime with proper scoping and control.
class MathEngine
[:add, :subtract].each do |operation|
define_method(operation) do |a, b|
operation == :add ? a + b : a - b
end
end
end
m = MathEngine.new
puts m.add(5, 3) # => 8
puts m.subtract(5, 3) # => 2
3. case/when Dispatching
Use case for controlling allowed operations instead of open-ended string evaluation.
def run_operation(op, a, b)
case op
when "add" then a + b
when "sub" then a - b
else "Unknown"
end
end
puts run_operation("add", 2, 3) # => 5
4. Gems like Dentaku
Dentaku is a safe, Ruby-based expression parser. It evaluates math and logic without running Ruby code.
calculator = Dentaku::Calculator.new
calculator.evaluate("10 * tax_rate", tax_rate: 0.15) # => 1.5
đ Real-World Example: Refactoring Code That Uses eval
Imagine you built a reporting feature in an internal admin dashboard where users enter formulas (e.g., "revenue - cost") to calculate profit. A naive solution might use eval like this:
def calculate_formula(formula, context)
context.each { |k, v| eval("#{k} = #{v}") }
eval(formula)
end
calculate_formula("revenue - cost", { revenue: 1000, cost: 300 })
# => 700
â ď¸ This approach is risky. If someone inputs `system('rm -rf /')` as the formula, the server could be destroyed.
đ Refactored Using Dentaku â a safe, embedded expression evaluator:
calculator = Dentaku::Calculator.new
calculator.evaluate("revenue - cost", revenue: 1000, cost: 300)
# => 700
đ§Š How eval Interacts with Rails Controllers and Models
In a Rails application, eval can execute dynamic Ruby code within the context of controllers, models, or views. This makes it powerfulâbut extremely dangerous when misused.
đ Example: Eval in a Controller
class ReportsController < ApplicationController
def custom
formula = params[:formula] # e.g., "Order.sum(:amount)"
result = eval(formula)
render plain: result
end
end
â ď¸ This allows dangerous methods like eval("User.destroy_all") or eval("`rm -rf /`") to be run from the URL!
đ Example: Eval in a Model
class Calculator < ApplicationRecord
def run(expression)
eval(expression)
end
end
calc = Calculator.new
calc.run("2 + 2") # => 4
Although it works, this exposes model logic to arbitrary code execution. An attacker could inject destructive commands if input isnât controlled.
eval in production controllers or models.đ Benchmarking: eval vs. send vs. method_missing in Rails
When building dynamic behavior in Ruby or Rails, developers often choose between eval, send, or method_missing. Each has different trade-offs in terms of performance, safety, and readability.
đ§Ş Benchmark Example
require 'benchmark'
class Demo
def greet; "Hello"; end
def method_missing(method, *args); greet if method == :dynamic_greet; end
end
demo = Demo.new
n = 100_000
Benchmark.bm do |x|
x.report("eval:") { n.times { eval("demo.greet") } }
x.report("send:") { n.times { demo.send(:greet) } }
x.report("method_missing:"){ n.times { demo.dynamic_greet } }
end
âď¸ Results (Approximate)
- send: â Fast and safe (best performance)
- method_missing: â ď¸ Slightly slower but flexible
- eval: â Significantly slower and unsafe
đ Summary Table
| Technique | Performance | Safety | Use Case |
|---|---|---|---|
| eval | â Slow | â Dangerous | Avoid unless sandboxed |
| send | â Fast | â Safe (if method list is controlled) | Calling known dynamic methods |
| method_missing | â ď¸ Moderate | â ď¸ Prone to bugs if not handled carefully | Metaprogramming DSLs |
send gives you all the power you needâwithout the risk. Use method_missing sparingly, and avoid eval unless there’s no alternative.đ Safe String Interpolation vs. eval in Dynamic Code
When you need to generate dynamic content, calculations, or method names in Ruby or Rails, it might seem tempting to use eval. However, in most cases, safe string interpolation or method dispatching will do the jobâwith none of the security concerns.
â Using eval (Unsafe)
user_input = "2 + 3"
result = eval(user_input) # => 5
This opens the door to malicious input like \`rm -rf /\` or accessing Rails internalsâdangerous in any environment!
â Safe Interpolation (Preferred)
user = "John"
message = "Hello, #{user}!" # => "Hello, John!"
Interpolation evaluates values already present in memory or variablesâno code execution involved.
đˇď¸ Use Case: Dynamic SQL with Placeholders (Rails Way)
min_price = 100
Product.where("price > ?", min_price)
Avoid eval("Product.where(\"price > #{user_input}\")"). Instead, use ActiveRecord’s built-in safety with placeholders to prevent SQL injection.
eval should be the last resort and always sandboxed if used.đŹ Behind the Scenes: How eval Works in Ruby
Rubyâs eval method takes a string and executes it as Ruby code. But internally, itâs much more than just ârunning a stringâ.
đ ď¸ What Happens Internally
- Parsing: The string is parsed into an Abstract Syntax Tree (AST) using Rubyâs built-in parser.
- Compilation: The AST is converted into bytecode that the Ruby virtual machine (YARV) can execute.
- Execution: The bytecode is executed in the current scope and binding context, which can access local and instance variables.
đ§ Example (With Explanation)
x = 10
eval("x + 5") # => 15
Here, eval sees the current binding (where x exists), parses the string "x + 5", compiles it, and executes it in that same scope.
đŚ Custom Bindings
context = binding
x = 100
eval("x * 2", context) # => 200
You can pass a binding object to control the scope where eval runs. This makes it more flexibleâbut still risky.
eval parses and compiles at runtime, itâs slower and more dangerous than regular code. Avoid it unless you’re building a trusted DSL or debugging tool.đ Examples of eval in Different Ruby/Rails Scenarios
eval("2 + 2")â4x = 10; eval("x * 3")â30eval("'Hello'.upcase")â"HELLO"eval("[1,2,3].map { |n| n * 2 }")â[2,4,6]eval("Time.now.year")â current yeareval("Rails.env")â environment like"development"eval("params[:id]")â dangerous ifparamsare unsafeeval("'a' * 5")â"aaaaa"eval("x = 100; x + 50")â150but pollutes scopeeval("[1, 2, 3].reduce(:+)")â6eval("`ls`")â â executes system commandeval("Math.sqrt(144)")â12.0eval("'#{2 + 2}'")â"4"eval("'#{Rails.root}'")â expands root patheval("{ a: 1, b: 2 }[:a]")â1eval("10.times.map { |i| i * i }")â array of squares
eval. Use them only in trusted contexts, and never expose eval to user input.đ§ Interview Questions and Answers on eval in Ruby/Rails
- Q1: What is
evalin Ruby?
A:evalis a method that evaluates a string as Ruby code at runtime.
eval("2 + 2")returns4. - Q2: Why is using
evalconsidered dangerous?
A: It executes arbitrary code, which can lead to security vulnerabilities like remote code execution (RCE).
Example:eval(params[:code])can let a user run anything on your server. - Q3: Can you give a real-world misuse of
evalin Rails?
A: Evaluating user-generated formulas in a controller usingeval.
eval(params[:formula])is dangerousâusers can run system commands. - Q4: What are safer alternatives to
eval?
A: Usesend,public_send,define_method, or parsing gems likeDentaku.
Example:user.send(:name)instead ofeval("user.name"). - Q5: How does
senddiffer fromeval?
A:sendcalls an existing method by symbol, whileevalinterprets any code.
user.send(:email)is safer and more performant. - Q6: Is
evalever acceptable to use?
A: Only in controlled environments like internal developer tools or sandboxesânever with user input. - Q7: How do you protect against
eval-based attacks?
A: Never useevalon user input. Use strong parameter validation, whitelisted operations, and gems likeDentakufor expression parsing. - Q8: What’s a safe way to evaluate math formulas from user input?
A: Use theDentakugem:
calculator.evaluate("price * qty", price: 10, qty: 5)safely returns50. - Q9: Can
evalaffect performance?
A: Yes,evalis slower than method dispatch likesendbecause it parses and compiles code at runtime. - Q10: How do you refactor existing
evalusage?
A: Identify the purpose of dynamic behavior. Replace withsend, case-based routing, or metaprogramming methods likedefine_method.
Example:# BAD eval("user.#{param}") # GOOD if %w[name email].include?(param) user.public_send(param) end
eval with structured, predictable logic.â
Best Practices: Using or Avoiding eval in Ruby/Rails
While eval gives dynamic capabilities in Ruby, its use comes with significant risks. Below are key practices to follow when dealing with dynamic evaluation in any Ruby or Rails codebase:
- Avoid eval with User Input: Never use
evalto execute code that includes user-provided values. This is the most common source of vulnerabilities. - Use
sendorpublic_send: For calling methods dynamically, these are far safer and more efficient thaneval. - Use
caseoriffor Dynamic Logic: Handle known operations using whitelisted logic instead of evaluating strings. - Whitelist Inputs: If dynamic behavior is required, strictly whitelist allowed values or operations before processing.
- Use a Safe Expression Parser: Use gems like
Dentakufor user-defined formulas or simple math evaluation. - Don’t use eval in Controllers or Models: Instead, move dynamic logic into service objects or use Rubyâs metaprogramming tools responsibly.
- Use
define_methodfor Dynamic Method Creation: If you must create methods dynamically, usedefine_methodinside classes or modules. - Isolate with Binding (if you must use eval): Always provide a
bindingobject to contain scope and reduce exposure. - Log and Audit Any eval Usage: If eval must exist, log usage, inputs, and context, and periodically audit the code.
- Benchmark Before Use:
evalis slow. Always compare againstsend,method_missing, or lambdas for performance-critical paths.
eval like a loaded weaponâuse it only when absolutely necessary, in trusted environments, and with strict input controls. Always prefer structured alternatives.đ External Resources on eval in Ruby/Rails
- StackOverflow â Why is eval evil?
- Practicing Ruby â Antipatterns: eval
- Rails Security Guide â Code Evaluation Warning
send, public_send, or define_method in production-grade Rails apps.


Join our affiliate program today and start earning up to 30% commissionâsign up now! https://shorturl.fm/i5Xf8
Join our affiliate program and watch your earnings skyrocketâsign up now! https://shorturl.fm/EVO3n
Start sharing, start earningâbecome our affiliate today! https://shorturl.fm/ulK1j
Turn traffic into cashâapply to our affiliate program today! https://shorturl.fm/PnUK0
Start sharing our link and start earning today! https://shorturl.fm/yX23d
Turn your traffic into cashâjoin our affiliate program! https://shorturl.fm/tbM5r