Injection Flaws in Rails
How Injection Flaws Manifests in Rails
Injection flaws in Rails applications typically occur when user input is incorporated into commands or queries without proper sanitization. The most common vectors are SQL injection through ActiveRecord queries, command injection via system calls, and template injection in ERB views.
SQL injection often happens when developers bypass ActiveRecord's built-in protections. Consider this vulnerable pattern:
# VULNERABLE: Direct string interpolation
User.where("email = '#{params[:email]}'")
An attacker can exploit this with ' OR '1'='1 to bypass authentication or extract data. The Rails-specific danger is that many developers assume ActiveRecord automatically prevents all injection, but string interpolation breaks this protection.
Command injection appears in Rails through system calls and shell interactions:
# VULNERABLE: System call with user input
`ls -la #{params[:path]}`
Here, an attacker could inject ; rm -rf / to execute arbitrary commands. Rails developers often use backticks or system() for quick scripting, making this a common vulnerability.
ERB template injection is Rails-specific due to its default template engine. Dangerous patterns include:
<%= params[:user_input] %> # Renders raw HTML/JS
Unlike other frameworks that use auto-escaping by default, Rails ERB requires explicit use of <%- %> or h() helper to prevent XSS injection through templates.
Mass assignment vulnerabilities are another Rails-specific injection vector:
# VULNERABLE: Unprotected mass assignment
User.create(params[:user])
Before Rails 4.2, this allowed attackers to set any model attribute, including admin flags or foreign keys, by crafting malicious parameter hashes.
Rails-Specific Detection
Detecting injection flaws in Rails requires understanding both the framework's conventions and its common anti-patterns. Static analysis tools like Brakeman can identify dangerous patterns, but runtime scanning catches issues Brakeman misses.
middleBrick's Rails-specific detection includes:
- ActiveRecord Query Analysis: Scans for direct string interpolation in
where(),find_by(), andexecute()calls, flagging patterns like"SELECT * FROM users WHERE email = '#{email}'" - Shell Command Detection: Identifies system calls with interpolated variables, backtick execution, and
Kernel.execusage with user input - ERB Template Scanning: Detects unescaped output in views, particularly
<%= %>without sanitization - Mass Assignment Analysis: Checks for unprotected
new(),create(), andupdate()calls with rawparamshashes - Serialization Vulnerabilities: Scans for YAML deserialization with user-controlled data, which can lead to remote code execution
For active testing, middleBrick sends payloads through your API endpoints to verify if injection is possible at runtime. For example, it tests SQL injection by sending quotes and SQL metacharacters to parameter endpoints and analyzing responses for SQL error messages or unexpected data exposure.
The CLI tool makes Rails security scanning part of your development workflow:
middlebrick scan https://api.yourservice.com/v1/users
This runs all 12 security checks, with special emphasis on Rails-specific injection vectors, and returns a security score with prioritized findings and remediation guidance.
Rails-Specific Remediation
Rails provides native protections that, when used correctly, prevent most injection flaws. The key is understanding and consistently applying these framework features.
SQL Injection Prevention:
# SAFE: Parameter binding
User.where("email = ?", params[:email])
# SAFE: Hash conditions (preferred)
User.where(email: params[:email])
# SAFE: Named bind variables
User.where("email = :email", email: params[:email])
Always use parameterized queries. Rails automatically handles escaping and type conversion, making SQL injection virtually impossible when these patterns are followed.
Command Injection Prevention:
# SAFE: Shell command sanitization
require 'shellwords'
command = "ls -la #{Shellwords.escape(params[:path])}"
# SAFEST: Avoid shell when possible
IO.popen(['ls', '-la', params[:path]])
Use Shellwords.escape for any shell interaction, or better yet, avoid the shell entirely by passing arguments as arrays to IO.popen or Open3.capture3.
ERB Template Protection:
<%= h(params[:user_input]) %> # Explicit escaping
<%= sanitize(params[:user_input], tags: []) %> # Allowlist approach
<%- params[:user_input] %> # Auto-escaping in newer Rails
Prefer sanitize with explicit allowlists over raw output. The h helper is shorter but less expressive about intent.
Mass Assignment Protection:
# Rails 4.2+ - Strong Parameters
params.require(:user).permit(:email, :name)
# Model-level protection
class User < ApplicationRecord
attr_protected :admin, :is_active
end
Always use Strong Parameters to explicitly whitelist acceptable attributes. Never trust raw params hashes for model creation or updates.
Serialization Security:
# UNSAFE: User-controlled YAML
YAML.load(params[:data])
# SAFE: Use safe_load with allowlist
YAML.safe_load(params[:data], permitted_classes: [Symbol, String])
Never use YAML.load with untrusted data. Always prefer YAML.safe_load with explicit class allowlists.
Frequently Asked Questions
How does middleBrick detect injection flaws in Rails applications?
What's the difference between middleBrick's CLI and GitHub Action for Rails security?
middlebrick scan <url>) is ideal for local development and manual testing of Rails APIs. You can run it during development to check endpoints before deployment. The GitHub Action integrates middleBrick into your CI/CD pipeline, automatically scanning your Rails API in staging or production-like environments on every pull request or deployment. The GitHub Action can fail builds if security scores drop below your threshold, ensuring injection vulnerabilities never reach production. Both tools use the same scanning engine but the GitHub Action adds automated gating and continuous monitoring capabilities.