better_html 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/better_html/ast/iterator.rb +3 -3
- data/lib/better_html/ast/node.rb +6 -2
- data/lib/better_html/errors.rb +2 -11
- data/lib/better_html/test_helper/ruby_node.rb +103 -0
- data/lib/better_html/test_helper/safe_erb/allowed_script_type.rb +29 -0
- data/lib/better_html/test_helper/safe_erb/base.rb +56 -0
- data/lib/better_html/test_helper/safe_erb/no_javascript_tag_helper.rb +34 -0
- data/lib/better_html/test_helper/safe_erb/no_statements.rb +40 -0
- data/lib/better_html/test_helper/safe_erb/script_interpolation.rb +65 -0
- data/lib/better_html/test_helper/safe_erb/tag_interpolation.rb +163 -0
- data/lib/better_html/test_helper/safe_erb_tester.rb +32 -285
- data/lib/better_html/tokenizer/location.rb +1 -1
- data/lib/better_html/version.rb +1 -1
- data/test/better_html/errors_test.rb +13 -0
- data/test/better_html/test_helper/ruby_node_test.rb +288 -0
- data/test/better_html/test_helper/safe_erb/allowed_script_type_test.rb +45 -0
- data/test/better_html/test_helper/safe_erb/no_javascript_tag_helper_test.rb +37 -0
- data/test/better_html/test_helper/safe_erb/no_statements_test.rb +128 -0
- data/test/better_html/test_helper/safe_erb/script_interpolation_test.rb +149 -0
- data/test/better_html/test_helper/safe_erb/tag_interpolation_test.rb +295 -0
- data/test/test_helper.rb +1 -0
- metadata +23 -7
- data/lib/better_html/test_helper/ruby_expr.rb +0 -117
- data/test/better_html/test_helper/ruby_expr_test.rb +0 -283
- data/test/better_html/test_helper/safe_erb_tester_test.rb +0 -450
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'better_html/test_helper/safe_erb/allowed_script_type'
|
3
|
+
|
4
|
+
module BetterHtml
|
5
|
+
module TestHelper
|
6
|
+
module SafeErb
|
7
|
+
class AllowedScriptTypeTest < ActiveSupport::TestCase
|
8
|
+
setup do
|
9
|
+
@config = BetterHtml::Config.new(
|
10
|
+
javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
|
11
|
+
javascript_attribute_names: [/\Aon/i, 'data-eval'],
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "allowed script type" do
|
16
|
+
errors = validate(<<-EOF).errors
|
17
|
+
<script type="text/javascript">
|
18
|
+
</script>
|
19
|
+
EOF
|
20
|
+
|
21
|
+
assert_predicate errors, :empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
test "disallowed script types" do
|
25
|
+
errors = validate(<<-EOF).errors
|
26
|
+
<script type="text/bogus">
|
27
|
+
</script>
|
28
|
+
EOF
|
29
|
+
|
30
|
+
assert_equal 1, errors.size
|
31
|
+
assert_equal 'type="text/bogus"', errors.first.location.source
|
32
|
+
assert_equal "text/bogus is not a valid type, valid types are text/javascript, text/template, text/html", errors.first.message
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def validate(data, template_language: :html)
|
37
|
+
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
38
|
+
tester = BetterHtml::TestHelper::SafeErb::AllowedScriptType.new(parser, config: @config)
|
39
|
+
tester.validate
|
40
|
+
tester
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'better_html/test_helper/safe_erb/no_javascript_tag_helper'
|
3
|
+
|
4
|
+
module BetterHtml
|
5
|
+
module TestHelper
|
6
|
+
module SafeErb
|
7
|
+
class NoJavascriptTagHelperTest < ActiveSupport::TestCase
|
8
|
+
setup do
|
9
|
+
@config = BetterHtml::Config.new(
|
10
|
+
javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
|
11
|
+
javascript_attribute_names: [/\Aon/i, 'data-eval'],
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "javascript_tag helper is not allowed because it parses as text and unsafe erb cannot be detected" do
|
16
|
+
errors = validate(<<-EOF).errors
|
17
|
+
<%= javascript_tag do %>
|
18
|
+
if (a < 1) { <%= unsafe %> }
|
19
|
+
<% end %>
|
20
|
+
EOF
|
21
|
+
|
22
|
+
assert_equal 1, errors.size
|
23
|
+
assert_equal '<%= javascript_tag do %>', errors.first.location.source
|
24
|
+
assert_includes "'javascript_tag do' syntax is deprecated; use inline <script> instead", errors.first.message
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def validate(data, template_language: :html)
|
29
|
+
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
30
|
+
tester = BetterHtml::TestHelper::SafeErb::NoJavascriptTagHelper.new(parser, config: @config)
|
31
|
+
tester.validate
|
32
|
+
tester
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'better_html/test_helper/safe_erb/no_statements'
|
3
|
+
|
4
|
+
module BetterHtml
|
5
|
+
module TestHelper
|
6
|
+
module SafeErb
|
7
|
+
class NoStatementsTest < ActiveSupport::TestCase
|
8
|
+
setup do
|
9
|
+
@config = BetterHtml::Config.new(
|
10
|
+
javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
|
11
|
+
javascript_attribute_names: [/\Aon/i, 'data-eval'],
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "<script> tag with non executable content type is ignored" do
|
16
|
+
errors = validate(<<-EOF).errors
|
17
|
+
<script type="text/html">
|
18
|
+
<a onclick="<%= unsafe %>">
|
19
|
+
</script>
|
20
|
+
EOF
|
21
|
+
|
22
|
+
assert_predicate errors, :empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
test "statements not allowed in script tags" do
|
26
|
+
errors = validate(<<-EOF).errors
|
27
|
+
<script type="text/javascript">
|
28
|
+
<% if foo? %>
|
29
|
+
bla
|
30
|
+
<% end %>
|
31
|
+
</script>
|
32
|
+
EOF
|
33
|
+
|
34
|
+
assert_equal 1, errors.size
|
35
|
+
assert_equal "<% if foo? %>", errors.first.location.source
|
36
|
+
assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
|
37
|
+
end
|
38
|
+
|
39
|
+
test "statements not allowed in script without specified type" do
|
40
|
+
errors = validate(<<-EOF).errors
|
41
|
+
<script>
|
42
|
+
<% if foo? %>
|
43
|
+
bla
|
44
|
+
<% end %>
|
45
|
+
</script>
|
46
|
+
EOF
|
47
|
+
|
48
|
+
assert_equal 1, errors.size
|
49
|
+
assert_equal "<% if foo? %>", errors.first.location.source
|
50
|
+
assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
|
51
|
+
end
|
52
|
+
|
53
|
+
test "statements not allowed in javascript template" do
|
54
|
+
errors = validate(<<-JS, template_language: :javascript).errors
|
55
|
+
<% if foo %>
|
56
|
+
bla
|
57
|
+
<% end %>
|
58
|
+
JS
|
59
|
+
|
60
|
+
assert_equal 1, errors.size
|
61
|
+
assert_equal "<% if foo %>", errors.first.location.source
|
62
|
+
assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
|
63
|
+
end
|
64
|
+
|
65
|
+
test "erb comments allowed in scripts" do
|
66
|
+
errors = validate(<<-EOF).errors
|
67
|
+
<script type="text/javascript">
|
68
|
+
<%# comment %>
|
69
|
+
</script>
|
70
|
+
EOF
|
71
|
+
|
72
|
+
assert_predicate errors, :empty?
|
73
|
+
end
|
74
|
+
|
75
|
+
test "script tag without content" do
|
76
|
+
errors = validate(<<-EOF).errors
|
77
|
+
<script type="text/javascript"></script>
|
78
|
+
EOF
|
79
|
+
|
80
|
+
assert_predicate errors, :empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
test "statement after script regression" do
|
84
|
+
errors = validate(<<-EOF).errors
|
85
|
+
<script type="text/javascript">
|
86
|
+
foo()
|
87
|
+
</script>
|
88
|
+
<% if condition? %>
|
89
|
+
EOF
|
90
|
+
|
91
|
+
assert_predicate errors, :empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
test "end statements are allowed in script tags" do
|
95
|
+
errors = validate(<<-EOF).errors
|
96
|
+
<script type="text/template">
|
97
|
+
<%= ui_form do %>
|
98
|
+
<div></div>
|
99
|
+
<% end %>
|
100
|
+
</script>
|
101
|
+
EOF
|
102
|
+
|
103
|
+
assert_predicate errors, :empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
test "statements are allowed in text/html tags" do
|
107
|
+
errors = validate(<<-EOF).errors
|
108
|
+
<script type="text/html">
|
109
|
+
<% if condition? %>
|
110
|
+
<div></div>
|
111
|
+
<% end %>
|
112
|
+
</script>
|
113
|
+
EOF
|
114
|
+
|
115
|
+
assert_predicate errors, :empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
def validate(data, template_language: :html)
|
120
|
+
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
121
|
+
tester = BetterHtml::TestHelper::SafeErb::NoStatements.new(parser, config: @config)
|
122
|
+
tester.validate
|
123
|
+
tester
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'better_html/test_helper/safe_erb/script_interpolation'
|
3
|
+
|
4
|
+
module BetterHtml
|
5
|
+
module TestHelper
|
6
|
+
module SafeErb
|
7
|
+
class ScriptInterpolationTest < ActiveSupport::TestCase
|
8
|
+
setup do
|
9
|
+
@config = BetterHtml::Config.new(
|
10
|
+
javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
|
11
|
+
javascript_attribute_names: [/\Aon/i, 'data-eval'],
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "multi line erb comments in text" do
|
16
|
+
errors = validate(<<-EOF).errors
|
17
|
+
text
|
18
|
+
<%#
|
19
|
+
this is a nice comment
|
20
|
+
!@\#{$%?&*()}
|
21
|
+
%>
|
22
|
+
EOF
|
23
|
+
|
24
|
+
assert_predicate errors, :empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
test "multi line erb comments in html attribute" do
|
28
|
+
errors = validate(<<-EOF).errors
|
29
|
+
<div title="
|
30
|
+
<%#
|
31
|
+
this is a comment right in the middle of an attribute for some reason
|
32
|
+
%>
|
33
|
+
">
|
34
|
+
EOF
|
35
|
+
|
36
|
+
assert_predicate errors, :empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
test "unsafe erb in <script> tag without type" do
|
40
|
+
errors = validate(<<-EOF).errors
|
41
|
+
<script>
|
42
|
+
if (a < 1) { <%= unsafe %> }
|
43
|
+
</script>
|
44
|
+
EOF
|
45
|
+
|
46
|
+
assert_equal 1, errors.size
|
47
|
+
assert_equal '<%= unsafe %>', errors.first.location.source
|
48
|
+
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
49
|
+
end
|
50
|
+
|
51
|
+
test "unsafe erb in javascript template" do
|
52
|
+
errors = validate(<<-JS, template_language: :javascript).errors
|
53
|
+
if (a < 1) { <%= unsafe %> }
|
54
|
+
JS
|
55
|
+
|
56
|
+
assert_equal 1, errors.size
|
57
|
+
assert_equal '<%= unsafe %>', errors.first.location.source
|
58
|
+
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
59
|
+
end
|
60
|
+
|
61
|
+
test "<script> tag without calls is unsafe" do
|
62
|
+
errors = validate(<<-EOF).errors
|
63
|
+
<script type="text/javascript">
|
64
|
+
if (a < 1) { <%= "unsafe" %> }
|
65
|
+
</script>
|
66
|
+
EOF
|
67
|
+
|
68
|
+
assert_equal 1, errors.size
|
69
|
+
assert_equal '<%= "unsafe" %>', errors.first.location.source
|
70
|
+
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
71
|
+
end
|
72
|
+
|
73
|
+
test "javascript template without calls is unsafe" do
|
74
|
+
errors = validate(<<-JS, template_language: :javascript).errors
|
75
|
+
if (a < 1) { <%= "unsafe" %> }
|
76
|
+
JS
|
77
|
+
|
78
|
+
assert_equal 1, errors.size
|
79
|
+
assert_equal '<%= "unsafe" %>', errors.first.location.source
|
80
|
+
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
81
|
+
end
|
82
|
+
|
83
|
+
test "unsafe erb in <script> tag with text/javascript content type" do
|
84
|
+
errors = validate(<<-EOF).errors
|
85
|
+
<script type="text/javascript">
|
86
|
+
if (a < 1) { <%= unsafe %> }
|
87
|
+
</script>
|
88
|
+
EOF
|
89
|
+
|
90
|
+
assert_equal 1, errors.size
|
91
|
+
assert_equal '<%= unsafe %>', errors.first.location.source
|
92
|
+
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
93
|
+
end
|
94
|
+
|
95
|
+
test "<script> with to_json is safe" do
|
96
|
+
errors = validate(<<-EOF).errors
|
97
|
+
<script type="text/javascript">
|
98
|
+
<%= unsafe.to_json %>
|
99
|
+
</script>
|
100
|
+
EOF
|
101
|
+
|
102
|
+
assert_predicate errors, :empty?
|
103
|
+
end
|
104
|
+
|
105
|
+
test "javascript template with to_json is safe" do
|
106
|
+
errors = validate(<<-JS, template_language: :javascript).errors
|
107
|
+
<%= unsafe.to_json %>
|
108
|
+
JS
|
109
|
+
|
110
|
+
assert_predicate errors, :empty?
|
111
|
+
end
|
112
|
+
|
113
|
+
test "<script> with raw and to_json is safe" do
|
114
|
+
errors = validate(<<-EOF).errors
|
115
|
+
<script type="text/javascript">
|
116
|
+
<%= raw unsafe.to_json %>
|
117
|
+
</script>
|
118
|
+
EOF
|
119
|
+
|
120
|
+
assert_predicate errors, :empty?
|
121
|
+
end
|
122
|
+
|
123
|
+
test "javascript template with raw and to_json is safe" do
|
124
|
+
errors = validate(<<-JS, template_language: :javascript).errors
|
125
|
+
<%= raw unsafe.to_json %>
|
126
|
+
JS
|
127
|
+
|
128
|
+
assert_predicate errors, :empty?
|
129
|
+
end
|
130
|
+
|
131
|
+
test "ivar missing .to_json is unsafe" do
|
132
|
+
errors = validate('<script><%= @feature.html_safe %></script>').errors
|
133
|
+
|
134
|
+
assert_equal 1, errors.size
|
135
|
+
assert_equal "<%= @feature.html_safe %>", errors.first.location.source
|
136
|
+
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def validate(data, template_language: :html)
|
141
|
+
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
142
|
+
tester = BetterHtml::TestHelper::SafeErb::ScriptInterpolation.new(parser, config: @config)
|
143
|
+
tester.validate
|
144
|
+
tester
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,295 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'better_html/test_helper/safe_erb/tag_interpolation'
|
3
|
+
|
4
|
+
module BetterHtml
|
5
|
+
module TestHelper
|
6
|
+
module SafeErb
|
7
|
+
class TagInterpolationTest < ActiveSupport::TestCase
|
8
|
+
setup do
|
9
|
+
@config = BetterHtml::Config.new(
|
10
|
+
javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
|
11
|
+
javascript_attribute_names: [/\Aon/i, 'data-eval'],
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "raw in <script> tag" do
|
16
|
+
errors = validate(<<-EOF).errors
|
17
|
+
<script>var myData = <%= raw(foo.to_json) %>;</script>
|
18
|
+
EOF
|
19
|
+
|
20
|
+
assert_equal 0, errors.size
|
21
|
+
end
|
22
|
+
|
23
|
+
test "html_safe in <script> tag" do
|
24
|
+
errors = validate(<<-EOF).errors
|
25
|
+
<script>var myData = <%= foo.to_json.html_safe %>;</script>
|
26
|
+
EOF
|
27
|
+
|
28
|
+
assert_equal 0, errors.size
|
29
|
+
end
|
30
|
+
|
31
|
+
test "<%== in <script> tag" do
|
32
|
+
errors = validate(<<-EOF).errors
|
33
|
+
<script>var myData = <%== foo.to_json %>;</script>
|
34
|
+
EOF
|
35
|
+
|
36
|
+
assert_equal 0, errors.size
|
37
|
+
end
|
38
|
+
|
39
|
+
test "string without interpolation is safe" do
|
40
|
+
errors = validate(<<-EOF).errors
|
41
|
+
<a onclick="alert('<%= "something" %>')">
|
42
|
+
EOF
|
43
|
+
|
44
|
+
assert_equal 0, errors.size
|
45
|
+
end
|
46
|
+
|
47
|
+
test "string with interpolation" do
|
48
|
+
errors = validate(<<-EOF).errors
|
49
|
+
<a onclick="<%= "hello \#{name}" %>">
|
50
|
+
EOF
|
51
|
+
|
52
|
+
assert_equal 1, errors.size
|
53
|
+
assert_equal 'name', errors.first.location.source
|
54
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
55
|
+
end
|
56
|
+
|
57
|
+
test "string with interpolation and ternary" do
|
58
|
+
errors = validate(<<-EOF).errors
|
59
|
+
<a onclick="<%= "hello \#{foo ? bar : baz}" if bla? %>">
|
60
|
+
EOF
|
61
|
+
|
62
|
+
assert_equal 2, errors.size
|
63
|
+
|
64
|
+
assert_equal 'bar', errors[0].location.source
|
65
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors[0].message
|
66
|
+
|
67
|
+
assert_equal 'baz', errors[1].location.source
|
68
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors[1].message
|
69
|
+
end
|
70
|
+
|
71
|
+
test "plain erb tag in html attribute" do
|
72
|
+
errors = validate(<<-EOF).errors
|
73
|
+
<a onclick="method(<%= unsafe %>)">
|
74
|
+
EOF
|
75
|
+
|
76
|
+
assert_equal 1, errors.size
|
77
|
+
assert_equal 'unsafe', errors.first.location.source
|
78
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
79
|
+
end
|
80
|
+
|
81
|
+
test "to_json is safe in html attribute" do
|
82
|
+
errors = validate(<<-EOF).errors
|
83
|
+
<a onclick="method(<%= unsafe.to_json %>)">
|
84
|
+
EOF
|
85
|
+
assert_predicate errors, :empty?
|
86
|
+
end
|
87
|
+
|
88
|
+
test "ternary with safe javascript escaping" do
|
89
|
+
errors = validate(<<-EOF).errors
|
90
|
+
<a onclick="method(<%= foo ? bar.to_json : j(baz) %>)">
|
91
|
+
EOF
|
92
|
+
assert_predicate errors, :empty?
|
93
|
+
end
|
94
|
+
|
95
|
+
test "ternary with unsafe javascript escaping" do
|
96
|
+
errors = validate(<<-EOF).errors
|
97
|
+
<a onclick="method(<%= foo ? bar : j(baz) %>)">
|
98
|
+
EOF
|
99
|
+
|
100
|
+
assert_equal 1, errors.size
|
101
|
+
assert_equal 'bar', errors.first.location.source
|
102
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
103
|
+
end
|
104
|
+
|
105
|
+
test "j is safe in html attribute" do
|
106
|
+
errors = validate(<<-EOF).errors
|
107
|
+
<a onclick="method('<%= j unsafe %>')">
|
108
|
+
EOF
|
109
|
+
assert_predicate errors, :empty?
|
110
|
+
end
|
111
|
+
|
112
|
+
test "j() is safe in html attribute" do
|
113
|
+
errors = validate(<<-EOF).errors
|
114
|
+
<a onclick="method('<%= j(unsafe) %>')">
|
115
|
+
EOF
|
116
|
+
assert_predicate errors, :empty?
|
117
|
+
end
|
118
|
+
|
119
|
+
test "escape_javascript is safe in html attribute" do
|
120
|
+
errors = validate(<<-EOF).errors
|
121
|
+
<a onclick="method(<%= escape_javascript unsafe %>)">
|
122
|
+
EOF
|
123
|
+
assert_predicate errors, :empty?
|
124
|
+
end
|
125
|
+
|
126
|
+
test "escape_javascript() is safe in html attribute" do
|
127
|
+
errors = validate(<<-EOF).errors
|
128
|
+
<a onclick="method(<%= escape_javascript(unsafe) %>)">
|
129
|
+
EOF
|
130
|
+
assert_predicate errors, :empty?
|
131
|
+
end
|
132
|
+
|
133
|
+
test "html_safe is never safe in html attribute, even non javascript attributes like href" do
|
134
|
+
errors = validate(<<-EOF).errors
|
135
|
+
<a href="<%= unsafe.html_safe %>">
|
136
|
+
EOF
|
137
|
+
|
138
|
+
assert_equal 1, errors.size
|
139
|
+
assert_equal 'unsafe.html_safe', errors.first.location.source
|
140
|
+
assert_equal "erb interpolation with '<%= (...).html_safe %>' in this context is never safe", errors.first.message
|
141
|
+
end
|
142
|
+
|
143
|
+
test "html_safe is never safe in html attribute, even with to_json" do
|
144
|
+
errors = validate(<<-EOF).errors
|
145
|
+
<a onclick="method(<%= unsafe.to_json.html_safe %>)">
|
146
|
+
EOF
|
147
|
+
|
148
|
+
assert_equal 2, errors.size
|
149
|
+
assert_equal 'unsafe.to_json.html_safe', errors[0].location.source
|
150
|
+
assert_equal "erb interpolation with '<%= (...).html_safe %>' in this context is never safe", errors[0].message
|
151
|
+
assert_equal 'unsafe.to_json.html_safe', errors[1].location.source
|
152
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors[1].message
|
153
|
+
end
|
154
|
+
|
155
|
+
test "<%== is never safe in html attribute, even non javascript attributes like href" do
|
156
|
+
errors = validate(<<-EOF).errors
|
157
|
+
<a href="<%== unsafe %>">
|
158
|
+
EOF
|
159
|
+
|
160
|
+
assert_equal 1, errors.size
|
161
|
+
assert_equal '<%== unsafe %>', errors.first.location.source
|
162
|
+
assert_includes "erb interpolation with '<%==' inside html attribute is never safe", errors.first.message
|
163
|
+
end
|
164
|
+
|
165
|
+
test "<%== is never safe in html attribute, even with to_json" do
|
166
|
+
errors = validate(<<-EOF).errors
|
167
|
+
<a onclick="method(<%== unsafe.to_json %>)">
|
168
|
+
EOF
|
169
|
+
|
170
|
+
assert_equal 1, errors.size
|
171
|
+
assert_equal '<%== unsafe.to_json %>', errors.first.location.source
|
172
|
+
assert_includes "erb interpolation with '<%==' inside html attribute is never safe", errors.first.message
|
173
|
+
end
|
174
|
+
|
175
|
+
test "raw is never safe in html attribute, even non javascript attributes like href" do
|
176
|
+
errors = validate(<<-EOF).errors
|
177
|
+
<a href="<%= raw unsafe %>">
|
178
|
+
EOF
|
179
|
+
|
180
|
+
assert_equal 1, errors.size
|
181
|
+
assert_equal 'raw unsafe', errors.first.location.source
|
182
|
+
assert_equal "erb interpolation with '<%= raw(...) %>' in this context is never safe", errors.first.message
|
183
|
+
end
|
184
|
+
|
185
|
+
test "raw is never safe in html attribute, even with to_json" do
|
186
|
+
errors = validate(<<-EOF).errors
|
187
|
+
<a onclick="method(<%= raw unsafe.to_json %>)">
|
188
|
+
EOF
|
189
|
+
|
190
|
+
assert_equal 2, errors.size
|
191
|
+
assert_equal 'raw unsafe.to_json', errors[0].location.source
|
192
|
+
assert_equal "erb interpolation with '<%= raw(...) %>' in this context is never safe", errors[0].message
|
193
|
+
assert_equal 'raw unsafe.to_json', errors[1].location.source
|
194
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors[1].message
|
195
|
+
end
|
196
|
+
|
197
|
+
test "unsafe javascript methods in helper calls with new hash syntax" do
|
198
|
+
errors = validate(<<-EOF).errors
|
199
|
+
<%= ui_my_helper(:foo, onclick: "alert(\#{unsafe})", onmouseover: "alert(\#{unsafe.to_json})") %>
|
200
|
+
EOF
|
201
|
+
|
202
|
+
assert_equal 1, errors.size
|
203
|
+
assert_equal "unsafe", errors[0].location.source
|
204
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors[0].message
|
205
|
+
end
|
206
|
+
|
207
|
+
test "unsafe javascript methods in helper calls with old hash syntax" do
|
208
|
+
errors = validate(<<-EOF).errors
|
209
|
+
<%= ui_my_helper(:foo, :onclick => "alert(\#{unsafe})") %>
|
210
|
+
EOF
|
211
|
+
|
212
|
+
assert_equal 1, errors.size
|
213
|
+
assert_equal "unsafe", errors.first.location.source
|
214
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
215
|
+
end
|
216
|
+
|
217
|
+
test "unsafe javascript methods in helper calls with more than one level of nested hash and :dstr" do
|
218
|
+
errors = validate(<<-EOF).errors
|
219
|
+
<%= ui_my_helper(:foo, inner_html: { onclick: "foo \#{unsafe}" }) %>
|
220
|
+
EOF
|
221
|
+
|
222
|
+
assert_equal 1, errors.size
|
223
|
+
assert_equal "unsafe", errors.first.location.source
|
224
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
225
|
+
end
|
226
|
+
|
227
|
+
test "safe javascript methods in helper calls with more than one level of nested hash and :dstr" do
|
228
|
+
errors = validate(<<-EOF).errors
|
229
|
+
<%= ui_my_helper(:foo, inner_html: { onclick: "foo \#{unsafe.to_json}" }) %>
|
230
|
+
EOF
|
231
|
+
|
232
|
+
assert_equal 0, errors.size
|
233
|
+
end
|
234
|
+
|
235
|
+
test "unsafe javascript methods in helper calls with string as key" do
|
236
|
+
errors = validate(<<-EOF).errors
|
237
|
+
<%= ui_my_helper(:foo, 'data-eval' => "alert(\#{unsafe})") %>
|
238
|
+
EOF
|
239
|
+
|
240
|
+
assert_equal 1, errors.size
|
241
|
+
assert_equal "unsafe", errors.first.location.source
|
242
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
243
|
+
end
|
244
|
+
|
245
|
+
test "unsafe javascript methods in helper calls with nested data key" do
|
246
|
+
errors = validate(<<-EOF).errors
|
247
|
+
<%= ui_my_helper(:foo, data: { eval: "alert(\#{unsafe})" }) %>
|
248
|
+
EOF
|
249
|
+
|
250
|
+
assert_equal 1, errors.size
|
251
|
+
assert_equal "unsafe", errors.first.location.source
|
252
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
253
|
+
end
|
254
|
+
|
255
|
+
test "unsafe javascript methods in helper calls with more than one level of nested data key" do
|
256
|
+
errors = validate(<<-EOF).errors
|
257
|
+
<%= ui_my_helper(:foo, inner_html: { data: { eval: "alert(\#{unsafe})" } }) %>
|
258
|
+
EOF
|
259
|
+
|
260
|
+
assert_equal 1, errors.size
|
261
|
+
assert_equal "unsafe", errors.first.location.source
|
262
|
+
assert_equal "erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'", errors.first.message
|
263
|
+
end
|
264
|
+
|
265
|
+
test "using raw anywhere in helpers" do
|
266
|
+
errors = validate(<<-EOF).errors
|
267
|
+
<%= ui_my_helper(:foo, help_text: raw("foo")) %>
|
268
|
+
EOF
|
269
|
+
|
270
|
+
assert_equal 1, errors.size
|
271
|
+
assert_equal "ui_my_helper(:foo, help_text: raw(\"foo\"))", errors.first.location.source
|
272
|
+
assert_equal "erb interpolation with '<%= raw(...) %>' in this context is never safe", errors.first.message
|
273
|
+
end
|
274
|
+
|
275
|
+
test "using raw anywhere in html tags" do
|
276
|
+
errors = validate(<<-EOF).errors
|
277
|
+
<a "<%= raw("hello") %>">
|
278
|
+
EOF
|
279
|
+
|
280
|
+
assert_equal 1, errors.size
|
281
|
+
assert_equal "raw(\"hello\")", errors.first.location.source
|
282
|
+
assert_equal "erb interpolation with '<%= raw(...) %>' in this context is never safe", errors.first.message
|
283
|
+
end
|
284
|
+
|
285
|
+
private
|
286
|
+
def validate(data, template_language: :html)
|
287
|
+
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
288
|
+
tester = BetterHtml::TestHelper::SafeErb::TagInterpolation.new(parser, config: @config)
|
289
|
+
tester.validate
|
290
|
+
tester
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|