Vulnerability
Rails

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 App

How 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

1

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]) %>
2

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)
  }
end
3

Audit 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')
end
4

Configure 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
  ]
end

Prevention 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.

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.