XSS in Rails Applications
Rails auto-escapes ERB output with <%= %>, but html_safe, raw(), and String#html_safe bypass this protection. Rails' convention-over-configuration approach means security headers require explicit setup, and many Rails apps lack Content Security Policy configuration.
Scan Your Rails AppHow XSS Manifests in Rails
Rails ERB templates auto-escape <%= variable %>, but developers bypass this with raw(), html_safe, and the <%== %> tag. Content from rich text editors (Action Text), markdown processors, and helper methods that return HTML all commonly use html_safe. Action Text, Rails' built-in rich text framework, sanitizes content by default but can be configured to allow dangerous attributes. Custom sanitizer configurations may inadvertently permit XSS payloads. Helper methods that build HTML (content_tag, tag helpers) are safe by default, but custom helpers that concatenate HTML strings and mark them as html_safe create XSS vulnerabilities.
Real-World Impact
A Rails e-commerce platform used raw() to render product descriptions with HTML formatting from sellers. An attacker registered as a seller and injected a keylogger script into a product description. The script captured payment card numbers as buyers entered them on the checkout page.
Step-by-Step Fix
Use Rails sanitize helper
Rails includes a built-in sanitize method that removes dangerous HTML.
<%# UNSAFE %>
<%= raw(user.bio) %>
<%= user.bio.html_safe %>
<%# SAFE %>
<%= sanitize(user.bio, tags: %w[b i em strong a p br], attributes: %w[href target rel]) %>Configure Content Security Policy
Use Rails' built-in CSP DSL in the initializer.
# config/initializers/content_security_policy.rb
Rails.application.configure do
config.content_security_policy do |policy|
policy.default_src :self
policy.script_src :self
policy.style_src :self, :unsafe_inline
policy.img_src :self, :data
policy.font_src :self
policy.connect_src :self
end
config.content_security_policy_nonce_generator = ->(request) {
SecureRandom.base64(16)
}
endAudit and fix custom helpers
Review helpers that use html_safe and add sanitization.
# UNSAFE helper
def format_comment(comment)
"<div class=\"comment\">#{comment.body}</div>".html_safe
end
# SAFE helper
def format_comment(comment)
content_tag(:div, sanitize(comment.body), class: 'comment')
endConfigure Action Text sanitizer
Ensure Action Text's sanitizer does not allow dangerous attributes.
# config/application.rb
config.after_initialize do
ActionText::ContentHelper.sanitizer = Rails::Html::SafeListSanitizer.new
ActionText::ContentHelper.allowed_tags = %w[
b i em strong a p br ul ol li h2 h3 blockquote pre code
]
ActionText::ContentHelper.allowed_attributes = %w[
href target rel class
]
endPrevention Best Practices
1. Never use raw(), html_safe, or <%== %> with user-controlled data. 2. Use Rails' built-in sanitize helper or the Loofah gem for HTML sanitization. 3. Configure Content Security Policy using Rails' built-in CSP DSL. 4. Audit Action Text sanitizer configuration. 5. Review custom helpers for html_safe usage.
How to Test
1. Search for raw(), html_safe, and <%== in your codebase. 2. Test each instance with <img src=x onerror=alert(1)> payloads. 3. Review Action Text content for XSS by submitting HTML in rich text fields. 4. Check custom helpers in app/helpers/ for html_safe usage. 5. Use Vibe App Scanner to automatically detect XSS patterns in your Rails application.
Frequently Asked Questions
Does Rails automatically prevent XSS?
Yes, Rails auto-escapes all ERB output with <%= %>. However, raw(), html_safe, and <%== %> bypass this protection. Rails also includes a sanitize helper and the Loofah gem for safe HTML rendering.
Is Action Text safe from XSS?
Action Text sanitizes content by default using a safelist sanitizer. However, custom configurations can weaken this protection. Always review your Action Text sanitizer settings and test with XSS payloads.
How do I add nonce-based CSP in Rails?
Rails has built-in CSP support. Configure it in config/initializers/content_security_policy.rb and set config.content_security_policy_nonce_generator. Use csp_meta_tag in your layout and javascript_tag with nonce: true.
Related Security Resources
Is Your Rails App Vulnerable to XSS?
VAS automatically scans for xss vulnerabilities in Rails applications and provides step-by-step remediation guidance with code examples.
Scans from $5, results in minutes. Get actionable fixes tailored to your Rails stack.