artmotion-xss_shield 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Trampoline Systems
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,76 @@
1
+ FIXME: THIS README IS NOT UP-TO-DATE.
2
+
3
+ This plugin provides XSS protection for views coded in HAML and RHTML.
4
+
5
+ ERB templates are sometimes used for HTML, and sometimes for
6
+ other kinds of languages (SQL, email templates, YAML etc.).
7
+ XSS Shield protects only those templates with .rhtml extension,
8
+ leaving templates with .erb extension unprotected.
9
+
10
+ === Quick start ===
11
+
12
+ Assuming you're using HAML for all your templates.
13
+
14
+ * Install plugin.
15
+ * Edit all your layout files and change:
16
+ = @content_for_layout
17
+ = yield(:foo) # Foo being usually :js or :css
18
+ to:
19
+ = @content_for_layout.mark_as_xss_protected
20
+ = yield(:foo).mark_as_xss_protected
21
+ * By this point your application should be runnanble,
22
+ but might need some tweaking here and there to avoid potential
23
+ double-escaping.
24
+
25
+ === How it works ===
26
+
27
+ It works by subclassing String into SafeString.
28
+ When HAML engine seems a "= foo" fragment it check if result of executing "foo"
29
+ is a SafeString. If it is - it copies it to the output, if it's anything else
30
+ (String, Integer, nil and so on) it HTML-escapes it first.
31
+
32
+ To avoid double-escaping output of h is a SafeString, as is everything you
33
+ mark as XSS-protected.
34
+ = h(@foo)
35
+ = @foo # fully equivalent to h(@foo)
36
+ = "X <br /> Y".mark_as_xss_protected
37
+
38
+ It would be cumbersome to require mark_as_xss_protected every time you use
39
+ some helper like render :partial or link_to, so some helpers are modified
40
+ to return SafeString.
41
+
42
+ = render :partial => "foo"
43
+ = link_to "Bar", :action => :bar
44
+
45
+ If you trust your helpers, make them as XSS-protected:
46
+
47
+ module Some::Module
48
+ mark_helpers_as_xss_protected :text_field, :check_box
49
+ end
50
+
51
+ Because it is not possible to alter syntactic keywords like yield
52
+ or instance variables like @content_for_layout to mark them automatically
53
+ as secure, layout files need some manual tweaking.
54
+
55
+ === Other template engines ===
56
+
57
+ If a templates uses some templating engine other than HAML or ERB,
58
+ or it uses ERB but has extension .erb not .rhtml, XSS Shield does not protect it.
59
+
60
+ However some helpers like link_to and button_to are patched by XSS Shield to
61
+ make them more secure, and this extra security will be there even when used
62
+ in an otherwise unprotected context.
63
+
64
+ For example with XSS shield
65
+ link_to "A & B", "/foo"
66
+ will return (marked as safe):
67
+ '<a href="/foo">A &amp; B</a>'
68
+ not (plain String):
69
+ '<a href="/foo">A & B</a>'
70
+
71
+ Also - RHTML protection only works with default ERB engine (erb.rb from Ruby base).
72
+ If you use some alternative ERB engine it probably won't work.
73
+
74
+ Adding support for alternative templating engine should be relatively straightforward.
75
+ It's mostly a matter of changing to_s to to_s_xss_protected in a few places
76
+ in their source.
data/init.rb ADDED
@@ -0,0 +1,16 @@
1
+ unless ENV['DISABLE_XSS_SHIELD']
2
+ puts "Loading XSS Shield"
3
+ require 'xss_shield'
4
+ else
5
+ class ::String
6
+ def mark_as_xss_protected
7
+ self
8
+ end
9
+ end
10
+
11
+ class ::NilClass
12
+ def mark_as_xss_protected
13
+ self
14
+ end
15
+ end
16
+ end
data/lib/gem_init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # delegate to original init.rb from the plugin
2
+ require File.dirname(__FILE__) + '/../init'
data/lib/xss_shield.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'xss_shield/safe_string'
2
+ require 'xss_shield/haml_hacks'
3
+ require 'xss_shield/erb_hacks'
4
+ require 'xss_shield/secure_helpers'
@@ -0,0 +1,111 @@
1
+ class XSSProtectedERB < ERB
2
+ class Compiler < ::ERB::Compiler
3
+ def compile(s)
4
+ out = Buffer.new(self)
5
+
6
+ content = ''
7
+ scanner = make_scanner(s)
8
+ scanner.scan do |token|
9
+ if scanner.stag.nil?
10
+ case token
11
+ when PercentLine
12
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
13
+ content = ''
14
+ out.push(token.to_s)
15
+ out.cr
16
+ when :cr
17
+ out.cr
18
+ when '<%', '<%=', '<%#'
19
+ scanner.stag = token
20
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
21
+ content = ''
22
+ when "\n"
23
+ content << "\n"
24
+ out.push("#{@put_cmd} #{content.dump}")
25
+ out.cr
26
+ content = ''
27
+ when '<%%'
28
+ content << '<%'
29
+ else
30
+ content << token
31
+ end
32
+ else
33
+ case token
34
+ when '%>'
35
+ case scanner.stag
36
+ when '<%'
37
+ if content[-1] == ?\n
38
+ content.chop!
39
+ out.push(content)
40
+ out.cr
41
+ else
42
+ out.push(content)
43
+ end
44
+ when '<%='
45
+ # NOTE: Changed lines
46
+ out.push("#{@insert_cmd}((#{content}).to_s_xss_protected)")
47
+ # NOTE: End changed lines
48
+ when '<%#'
49
+ # out.push("# #{content.dump}")
50
+ end
51
+ scanner.stag = nil
52
+ content = ''
53
+ when '%%>'
54
+ content << '%>'
55
+ else
56
+ content << token
57
+ end
58
+ end
59
+ end
60
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
61
+ out.close
62
+ out.script
63
+ end
64
+ end
65
+
66
+ def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
67
+ @safe_level = safe_level
68
+ compiler = XSSProtectedERB::Compiler.new(trim_mode)
69
+ set_eoutvar(compiler, eoutvar)
70
+ @src = compiler.compile(str)
71
+ @filename = nil
72
+ end
73
+ end
74
+
75
+ module ActionView
76
+ class Base
77
+ private
78
+ def create_template_source(extension, template, render_symbol, locals)
79
+ if template_requires_setup?(extension)
80
+ body = case extension.to_sym
81
+ when :rxml, :builder
82
+ content_type_handler = (controller.respond_to?(:response) ? "controller.response" : "controller")
83
+ "#{content_type_handler}.content_type ||= Mime::XML\n" +
84
+ "xml = Builder::XmlMarkup.new(:indent => 2)\n" +
85
+ template +
86
+ "\nxml.target!\n"
87
+ when :rjs
88
+ "controller.response.content_type ||= Mime::JS\n" +
89
+ "update_page do |page|\n#{template}\nend"
90
+ end
91
+ # NOTE: Changed lines
92
+ elsif extension.to_sym == :rhtml
93
+ body = XSSProtectedERB.new(template, nil, @@erb_trim_mode).src
94
+ # NOTE: End changed lines
95
+ else
96
+ body = ERB.new(template, nil, @@erb_trim_mode).src
97
+ end
98
+
99
+ @@template_args[render_symbol] ||= {}
100
+ locals_keys = @@template_args[render_symbol].keys | locals
101
+ @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h }
102
+
103
+ locals_code = ""
104
+ locals_keys.each do |key|
105
+ locals_code << "#{key} = local_assigns[:#{key}]\n"
106
+ end
107
+
108
+ "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,42 @@
1
+ raise "Haml not loaded" unless Haml::Engine.instance_method(:push_script)
2
+
3
+ module Haml
4
+ class Engine
5
+ def push_script(text, flattened)
6
+ unless options[:suppress_eval]
7
+ push_silent("haml_temp = #{text}", true)
8
+ push_silent("haml_temp = haml_temp.to_s_xss_protected", true)
9
+ out = "haml_temp = _hamlout.push_script(haml_temp, #{@output_tabs}, #{flattened})\n"
10
+ if @block_opened
11
+ push_and_tabulate([:loud, out])
12
+ else
13
+ @precompiled << out
14
+ end
15
+ end
16
+ end
17
+
18
+ def build_attributes(attributes = {})
19
+ # We ignore @options[:attr_wrapper] because ERB::Util.h does not espace ' to &apos;
20
+ # making ' as attribute quote not workable
21
+ result = attributes.map do |a,v|
22
+ v = v.to_s_xss_protected
23
+ unless v.blank?
24
+ " #{a}=\"#{v}\""
25
+ end
26
+ end
27
+ result.sort.join
28
+ end
29
+ end
30
+
31
+ class Buffer
32
+ def build_attributes(attributes = {})
33
+ result = attributes.map do |a,v|
34
+ v = v.to_s_xss_protected
35
+ unless v.blank?
36
+ " #{a}=\"#{v}\""
37
+ end
38
+ end
39
+ result.sort.join
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ class SafeString < String
2
+ def to_s
3
+ self
4
+ end
5
+ def to_s_xss_protected
6
+ self
7
+ end
8
+ end
9
+
10
+ class String
11
+ def mark_as_xss_protected
12
+ SafeString.new(self)
13
+ end
14
+ end
15
+
16
+ class NilClass
17
+ def mark_as_xss_protected
18
+ self
19
+ end
20
+ end
21
+
22
+ # ERB::Util.h and (include ERB::Util; h) are different methods
23
+ module ERB::Util
24
+ class <<self
25
+ def h_with_xss_protection(*args)
26
+ h_without_xss_protection(*args).mark_as_xss_protected
27
+ end
28
+ alias_method_chain :h, :xss_protection
29
+ end
30
+
31
+ def h_with_xss_protection(*args)
32
+ h_without_xss_protection(*args).mark_as_xss_protected
33
+ end
34
+ alias_method_chain :h, :xss_protection
35
+ end
36
+
37
+ class Object
38
+ def to_s_xss_protected
39
+ ERB::Util.h(to_s).mark_as_xss_protected
40
+ end
41
+ end
42
+
43
+ class Array
44
+ def join_xss_protected(sep="")
45
+ map(&:to_s_xss_protected).join(sep.to_s_xss_protected).mark_as_xss_protected
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ class Module
2
+ def mark_helpers_as_xss_protected(*ms)
3
+ ms.each do |m|
4
+ begin
5
+ instance_method("#{m}_with_xss_protection")
6
+ rescue NameError
7
+ define_method :"#{m}_with_xss_protection" do |*args|
8
+ send(:"#{m}_without_xss_protection", *args).mark_as_xss_protected
9
+ end
10
+ alias_method_chain m, :xss_protection
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class ActionView::Base
17
+ mark_helpers_as_xss_protected :javascript_include_tag,
18
+ :stylesheet_link_tag,
19
+ :render,
20
+ :text_field_tag,
21
+ :submit_tag,
22
+ :radio_button,
23
+ :text_area,
24
+ :auto_discovery_link_tag,
25
+ :image_tag
26
+
27
+ def link_to_with_xss_protection(text, *args)
28
+ link_to_without_xss_protection(text.to_s_xss_protected, *args).mark_as_xss_protected
29
+ end
30
+ alias_method_chain :link_to, :xss_protection
31
+
32
+ def button_to_with_xss_protection(text, *args)
33
+ button_to_without_xss_protection(text.to_s_xss_protected, *args).mark_as_xss_protected
34
+ end
35
+ alias_method_chain :button_to, :xss_protection
36
+ end
37
+
38
+ module ActionView::Helpers::FormHelper
39
+ mark_helpers_as_xss_protected :text_field, :check_box
40
+ end
@@ -0,0 +1,40 @@
1
+ # Run from your Rails main directory
2
+ require 'test/test_helper'
3
+
4
+ class TestActionViewIntegration < Test::Unit::TestCase
5
+ def assert_renders(expected, input, extension)
6
+ base = ActionView::Base.new
7
+ actual = base.render_template(extension, input, "foo.#{extension}")
8
+ assert_equal expected, actual
9
+ end
10
+
11
+ def test_erb
12
+ assert_renders <<OUT, <<IN, :erb
13
+ A & B
14
+ A & B
15
+ OUT
16
+ <%= "A & B" %>
17
+ <%= "A & B".mark_as_xss_protected %>
18
+ IN
19
+ end
20
+
21
+ def test_rhtml
22
+ assert_renders <<OUT, <<IN, :rhtml
23
+ A &amp; B
24
+ A & B
25
+ OUT
26
+ <%= "A & B" %>
27
+ <%= "A & B".mark_as_xss_protected %>
28
+ IN
29
+ end
30
+
31
+ def test_haml
32
+ assert_renders <<OUT, <<IN, :haml
33
+ A &amp; B
34
+ A & B
35
+ OUT
36
+ = "A & B"
37
+ = "A & B".mark_as_xss_protected
38
+ IN
39
+ end
40
+ end
data/test/test_erb.rb ADDED
@@ -0,0 +1,44 @@
1
+ # Run from your Rails main directory
2
+ require 'test/test_helper'
3
+
4
+ class TestERB < Test::Unit::TestCase
5
+ def assert_renders_erb(expected, input, shield=true)
6
+ erb_class = shield ? XSSProtectedERB : ERB
7
+
8
+ actual = eval(erb_class.new(input).src)
9
+
10
+ assert_equal expected, actual
11
+ end
12
+
13
+ def test_erb_with_shield
14
+ assert_renders_erb <<OUT, <<IN, true
15
+ Foo &amp;amp; Bar
16
+ Foo &amp;amp; Bar
17
+ Foo &amp; Bar
18
+ Foo &amp; Bar
19
+ Foo &amp; Bar
20
+ OUT
21
+ <%= "Foo &amp; Bar" %>
22
+ <%= h("Foo &amp; Bar") %>
23
+ <%= "Foo &amp; Bar".mark_as_xss_protected %>
24
+ <%= h("Foo & Bar") %>
25
+ <%= "Foo & Bar" %>
26
+ IN
27
+ end
28
+
29
+ def test_erb_without_shield
30
+ assert_renders_erb <<OUT, <<IN, false
31
+ Foo &amp;amp; Bar
32
+ Foo &amp; Bar
33
+ Foo &amp; Bar
34
+ Foo &amp; Bar
35
+ Foo & Bar
36
+ OUT
37
+ <%= h("Foo &amp; Bar") %>
38
+ <%= "Foo &amp; Bar" %>
39
+ <%= "Foo &amp; Bar".mark_as_xss_protected %>
40
+ <%= h("Foo & Bar") %>
41
+ <%= "Foo & Bar" %>
42
+ IN
43
+ end
44
+ end
data/test/test_haml.rb ADDED
@@ -0,0 +1,43 @@
1
+ # Run from your Rails main directory
2
+ require 'test/test_helper'
3
+
4
+ class TestHaml < Test::Unit::TestCase
5
+ def setup
6
+ @base = ActionView::Base.new
7
+ end
8
+
9
+ def assert_haml_renders(expected, input)
10
+ actual = Haml::Engine.new(input).to_html(@base)
11
+ assert_equal expected, actual
12
+ end
13
+
14
+ def test_haml_engine
15
+ assert_haml_renders <<OUT, <<IN
16
+ A & B
17
+ C &amp; D
18
+ E &amp; F
19
+ G & H
20
+ I &amp; J
21
+ OUT
22
+ A & B
23
+ = "C & D"
24
+ = h("E & F")
25
+ = "G & H".mark_as_xss_protected
26
+ = "I & J".to_s_xss_protected
27
+ IN
28
+ end
29
+
30
+ def test_attribute_escaping_in_haml
31
+ @base.instance_eval {
32
+ @foo = "A < & > ' \" B"
33
+ }
34
+ assert_haml_renders <<OUT, <<IN
35
+ <div foo="A &lt; &amp; &gt; ' &quot; B" />
36
+ <div foo="A < & > ' " B" />
37
+ OUT
38
+ %div{:foo => @foo}/
39
+ %div{:foo => @foo.mark_as_xss_protected}/
40
+ IN
41
+ # Note that '/" explicitly marked as XSS-protected can break validity
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ # Run from your Rails main directory
2
+ require 'test/test_helper'
3
+
4
+ class TestHelpers < Test::Unit::TestCase
5
+ def setup
6
+ @base = ActionView::Base.new
7
+ end
8
+
9
+ def assert_haml_renders(expected, input)
10
+ actual = Haml::Engine.new(input).to_html(@base)
11
+ assert_equal expected, actual
12
+ end
13
+
14
+ def test_link_to
15
+ assert_haml_renders <<OUT, <<IN
16
+ <a href="/bar">Foo</a>
17
+ <a href="/bar">Foo &amp; Bar</a>
18
+ <a href="/bar">Foo & Bar</a>
19
+ OUT
20
+ = link_to "Foo", "/bar"
21
+ = link_to "Foo & Bar", "/bar"
22
+ = link_to "Foo & Bar".mark_as_xss_protected, "/bar"
23
+ IN
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ # Run from your Rails main directory
2
+ require 'test/test_helper'
3
+
4
+ class TestSafeString < Test::Unit::TestCase
5
+ def test_safe_string
6
+ assert_equal "foo", "foo".to_s_xss_protected
7
+ assert_equal "foo &amp; bar", "foo & bar".to_s_xss_protected
8
+ assert_equal "foo &amp; bar", "foo & bar".to_s_xss_protected
9
+ assert_equal "foo &amp;amp; bar", "foo &amp; bar".to_s_xss_protected
10
+ assert_equal "foo &amp; bar", "foo & bar".to_s_xss_protected.to_s_xss_protected
11
+ assert_equal "foo &amp; bar", h("foo & bar").to_s_xss_protected
12
+ assert_equal "foo &amp;amp; bar", h(h("foo & bar"))
13
+
14
+ assert_not_equal "foo".mark_as_xss_protected.object_id, "foo".mark_as_xss_protected.object_id
15
+ x = "foo & bar".mark_as_xss_protected
16
+ assert_equal x.mark_as_xss_protected, x
17
+ # Not sure if this makes sense
18
+ assert_not_equal x.mark_as_xss_protected.object_id, x.object_id
19
+
20
+ assert_equal x.to_s, x
21
+ assert_equal x.to_s.object_id, x.object_id
22
+ end
23
+
24
+ def test_nonstring_objects
25
+ assert_equal "15", 15.to_s_xss_protected
26
+ assert_equal SafeString, 15.to_s_xss_protected.class
27
+ end
28
+
29
+ def test_nil
30
+ assert_equal "", nil.to_s_xss_protected
31
+ assert_equal SafeString, nil.to_s_xss_protected.class
32
+ assert_equal nil, nil.mark_as_xss_protected
33
+ end
34
+
35
+ def test_join
36
+ assert_equal "", [].join_xss_protected
37
+ assert_equal "", [].join_xss_protected(",")
38
+ assert_equal "a", ["a"].join_xss_protected
39
+ assert_equal "a", ["a"].join_xss_protected(",")
40
+ assert_equal "ab", ["a", "b"].join_xss_protected
41
+ assert_equal "a,b", ["a", "b"].join_xss_protected(",")
42
+
43
+ assert_equal "a&amp;b", ["a", "b"].join_xss_protected("&")
44
+ assert_equal "a&amp;amp;b", ["a", "b"].join_xss_protected("&amp;")
45
+ assert_equal "a&amp;b", ["a", "b"].join_xss_protected("&amp;".mark_as_xss_protected)
46
+
47
+ assert_equal "&lt;&amp;&gt;", ["<", ">"].join_xss_protected("&")
48
+ assert_equal "&lt;&amp;amp;&gt;", ["<", ">"].join_xss_protected("&amp;")
49
+ assert_equal "&lt;&amp;&gt;", ["<", ">"].join_xss_protected("&amp;".mark_as_xss_protected)
50
+
51
+ assert_equal "< &amp; &gt;", ["<".mark_as_xss_protected, ">"].join_xss_protected(" & ")
52
+ assert_equal "&lt; &amp; >", ["<", ">".mark_as_xss_protected].join_xss_protected(" & ")
53
+ assert_equal "&lt; & &gt;", ["<", ">"].join_xss_protected(" & ".mark_as_xss_protected)
54
+ end
55
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: artmotion-xss_shield
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tomasz Wegrzanowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-26 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: This plugin provides XSS protection for views coded in HAML and RHTML. ERB templates are sometimes used for HTML, and sometimes for other kinds of languages (SQL, email templates, YAML etc.). XSS Shield protects only those templates with .rhtml extension, leaving templates with .erb extension unprotected.
17
+ email: ""
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - MIT-LICENSE
26
+ - README
27
+ - init.rb
28
+ - lib/xss_shield
29
+ - lib/xss_shield/safe_string.rb
30
+ - lib/xss_shield/haml_hacks.rb
31
+ - lib/xss_shield/erb_hacks.rb
32
+ - lib/xss_shield/secure_helpers.rb
33
+ - lib/gem_init.rb
34
+ - lib/xss_shield.rb
35
+ - test/test_helpers.rb
36
+ - test/test_actionview_integration.rb
37
+ - test/test_erb.rb
38
+ - test/test_haml.rb
39
+ - test/test_safe_string.rb
40
+ has_rdoc: false
41
+ homepage: http://code.google.com/p/xss-shield/
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.2.0
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: XSS Shield protects your views against cross-site scripting attacks without error-prone manual escaping with h().
66
+ test_files:
67
+ - test/test_helpers.rb
68
+ - test/test_actionview_integration.rb
69
+ - test/test_erb.rb
70
+ - test/test_haml.rb
71
+ - test/test_safe_string.rb