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 +20 -0
- data/README +76 -0
- data/init.rb +16 -0
- data/lib/gem_init.rb +2 -0
- data/lib/xss_shield.rb +4 -0
- data/lib/xss_shield/erb_hacks.rb +111 -0
- data/lib/xss_shield/haml_hacks.rb +42 -0
- data/lib/xss_shield/safe_string.rb +47 -0
- data/lib/xss_shield/secure_helpers.rb +40 -0
- data/test/test_actionview_integration.rb +40 -0
- data/test/test_erb.rb +44 -0
- data/test/test_haml.rb +43 -0
- data/test/test_helpers.rb +25 -0
- data/test/test_safe_string.rb +55 -0
- metadata +71 -0
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 & 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
data/lib/gem_init.rb
ADDED
data/lib/xss_shield.rb
ADDED
@@ -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 '
|
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 & 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 & 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; Bar
|
16
|
+
Foo &amp; Bar
|
17
|
+
Foo & Bar
|
18
|
+
Foo & Bar
|
19
|
+
Foo & Bar
|
20
|
+
OUT
|
21
|
+
<%= "Foo & Bar" %>
|
22
|
+
<%= h("Foo & Bar") %>
|
23
|
+
<%= "Foo & 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; Bar
|
32
|
+
Foo & Bar
|
33
|
+
Foo & Bar
|
34
|
+
Foo & Bar
|
35
|
+
Foo & Bar
|
36
|
+
OUT
|
37
|
+
<%= h("Foo & Bar") %>
|
38
|
+
<%= "Foo & Bar" %>
|
39
|
+
<%= "Foo & 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 & D
|
18
|
+
E & F
|
19
|
+
G & H
|
20
|
+
I & 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 < & > ' " 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 & 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 & bar", "foo & bar".to_s_xss_protected
|
8
|
+
assert_equal "foo & bar", "foo & bar".to_s_xss_protected
|
9
|
+
assert_equal "foo &amp; bar", "foo & bar".to_s_xss_protected
|
10
|
+
assert_equal "foo & bar", "foo & bar".to_s_xss_protected.to_s_xss_protected
|
11
|
+
assert_equal "foo & bar", h("foo & bar").to_s_xss_protected
|
12
|
+
assert_equal "foo &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&b", ["a", "b"].join_xss_protected("&")
|
44
|
+
assert_equal "a&amp;b", ["a", "b"].join_xss_protected("&")
|
45
|
+
assert_equal "a&b", ["a", "b"].join_xss_protected("&".mark_as_xss_protected)
|
46
|
+
|
47
|
+
assert_equal "<&>", ["<", ">"].join_xss_protected("&")
|
48
|
+
assert_equal "<&amp;>", ["<", ">"].join_xss_protected("&")
|
49
|
+
assert_equal "<&>", ["<", ">"].join_xss_protected("&".mark_as_xss_protected)
|
50
|
+
|
51
|
+
assert_equal "< & >", ["<".mark_as_xss_protected, ">"].join_xss_protected(" & ")
|
52
|
+
assert_equal "< & >", ["<", ">".mark_as_xss_protected].join_xss_protected(" & ")
|
53
|
+
assert_equal "< & >", ["<", ">"].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
|