Tom Lehman
Tom Lehman

Reputation: 89223

Get Rails 3 to sanitize output by default instead of escaping it

By default, Rails 3 escapes strings you output directly – e.g., <%= '<h1>' %> renders as &lt;h1&gt;

Because of this I have to annoyingly do this a lot:

<%= sanitize @post.body %>

Is there any way I can make this the default? I.e., I want this:

<%= @post.body %>

to be equivalent to:

<%= sanitize @post.body %>

instead of:

<%= h @post.body %>

as it is by default

Upvotes: 3

Views: 527

Answers (2)

Tom Lehman
Tom Lehman

Reputation: 89223

Based on Tass' answer, I feel like this might work (but I'm not sure):

class ActiveSupport::SafeBuffer
  def concat(value)
    if dirty? || value.html_safe?
      super(value)
    else
      # super(ERB::Util.h(value)) # this is what Rails does by default
      super(ActionController::Base.helpers.sanitize(value))
    end
  end
end

Upvotes: 1

Reactormonk
Reactormonk

Reputation: 21700

class ActiveSupport::SafeBuffer
  def concat(value)
    super(ERB::Util.h(value))
  end
  alias << concat
  def dirty?
    false
  end
end

Have fun being XSS'd. Do not use in production. This does disable XSS protection entirely and you can't even explicitly tell a piece of data is unsafe. I'd rather do

class Post
  def body_with_raw
    body_without_raw.html_safe
  end
  alias_method_chain :body, :raw
end

or even

class ActiveRecord::Base
  def self.html_safe(*attributes)
    attributes.each do |attribute|
      name = attribute + "with_raw"
      before = attribute + "without_raw"
      define_method name do
        before.html_safe
      end
      alias_method_chain attribute, "raw"
    end
  end
end

so you can

class Post
  html_safe :body
end

Upvotes: 2

Related Questions