Rails_xss Plugin

I installed the rails_xss plugin, for
the main purpose of seeing what will
break with Rails 3.0 (where the behaviour
of the plugin is the default). I think
I've fixed everything, but let me know if you
see stuff that is HTML-escaped, which
shouldn't be.

As a side benefit, we now use Erubis,
rather than ERB, to render templates.
They tell me it's faster ...
This commit is contained in:
Jacques Distler 2010-05-26 00:27:49 -05:00
parent d6be09e0f0
commit a5e08f7bcc
343 changed files with 43874 additions and 37 deletions

View file

@ -0,0 +1,3 @@
require 'rails_xss/erubis'
require 'rails_xss/action_view'
require 'rails_xss/string_ext'

View file

@ -0,0 +1,83 @@
module ActionView
class Base
def self.xss_safe?
true
end
module WithSafeOutputBuffer
# Rails version of with_output_buffer uses '' as the default buf
def with_output_buffer(buf = ActiveSupport::SafeBuffer.new) #:nodoc:
super buf
end
end
include WithSafeOutputBuffer
end
module Helpers
module TextHelper
def concat(string, unused_binding = nil)
if unused_binding
ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.", caller)
end
output_buffer.concat(string)
end
end
module TagHelper
private
def content_tag_string_with_escaping(name, content, options, escape = true)
content_tag_string_without_escaping(name, ERB::Util.h(content), options, escape)
end
alias_method_chain :content_tag_string, :escaping
end
end
end
module RailsXss
module SafeHelpers
def safe_helper(*names)
names.each do |helper_method_name|
aliased_target, punctuation = helper_method_name.to_s.sub(/([?!=])$/, ''), $1
module_eval <<-END
def #{aliased_target}_with_xss_safety#{punctuation}(*args, &block)
raw(#{aliased_target}_without_xss_safety#{punctuation}(*args, &block))
end
END
alias_method_chain helper_method_name, :xss_safety
end
end
end
module HelperOverrides
def link_to(*args, &block)
if block_given?
options = args.first || {}
html_options = args.second
concat(link_to(capture(&block), options, html_options))
else
name = args.first
options = args.second || {}
html_options = args.third
url = url_for(options)
if html_options
html_options = html_options.stringify_keys
href = html_options['href']
convert_options_to_javascript!(html_options, url)
tag_options = tag_options(html_options)
else
tag_options = nil
end
href_attr = "href=\"#{url}\"" unless href
"<a #{href_attr}#{tag_options}>#{ERB::Util.h(name || url)}</a>".html_safe
end
end
end
end
Module.class_eval { include RailsXss::SafeHelpers }
ActionController::Base.helper(RailsXss::HelperOverrides)

View file

@ -0,0 +1,33 @@
require 'erubis/helpers/rails_helper'
module RailsXss
class Erubis < ::Erubis::Eruby
def add_preamble(src)
src << "@output_buffer = ActiveSupport::SafeBuffer.new;"
end
def add_text(src, text)
return if text.empty?
src << "@output_buffer.safe_concat('" << escape_text(text) << "');"
end
def add_expr_literal(src, code)
if code =~ /\s*raw\s+(.*)/
src << "@output_buffer.safe_concat((" << $1 << ").to_s);"
else
src << '@output_buffer << ((' << code << ').to_s);'
end
end
def add_expr_escaped(src, code)
src << '@output_buffer << ' << escaped_expr(code) << ';'
end
def add_postamble(src)
src << '@output_buffer.to_s'
end
end
end
Erubis::Helpers::RailsHelper.engine_class = RailsXss::Erubis
Erubis::Helpers::RailsHelper.show_src = false

View file

@ -0,0 +1,52 @@
require 'active_support/deprecation'
ActiveSupport::SafeBuffer.class_eval do
def concat(value)
if value.html_safe?
super(value)
else
super(ERB::Util.h(value))
end
end
alias << concat
end
class String
def html_safe?
defined?(@_rails_html_safe)
end
def html_safe!
ActiveSupport::Deprecation.warn("Use html_safe with your strings instead of html_safe! See http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/ for the full story.", caller)
@_rails_html_safe = true
self
end
def add_with_safety(other)
result = add_without_safety(other)
if html_safe? && also_html_safe?(other)
result.html_safe!
else
result
end
end
alias_method :add_without_safety, :+
alias_method :+, :add_with_safety
def concat_with_safety(other_or_fixnum)
result = concat_without_safety(other_or_fixnum)
unless html_safe? && also_html_safe?(other_or_fixnum)
remove_instance_variable(:@_rails_html_safe) if defined?(@_rails_html_safe)
end
result
end
alias_method_chain :concat, :safety
undef_method :<<
alias_method :<<, :concat_with_safety
private
def also_html_safe?(other)
other.respond_to?(:html_safe?) && other.html_safe?
end
end

View file

@ -0,0 +1,4 @@
# desc "Explaining what the task does"
# task :rails_xss do
# # Task goes here
# end