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
@@ -1,450 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'better_html/test_helper/safe_erb_tester'
|
3
|
-
|
4
|
-
module BetterHtml
|
5
|
-
module TestHelper
|
6
|
-
class SafeErbTesterTest < ActiveSupport::TestCase
|
7
|
-
setup do
|
8
|
-
@config = BetterHtml::Config.new(
|
9
|
-
javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
|
10
|
-
javascript_attribute_names: [/\Aon/i, 'data-eval'],
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
test "multi line erb comments in text" do
|
15
|
-
errors = parse(<<-EOF).errors
|
16
|
-
text
|
17
|
-
<%#
|
18
|
-
this is a nice comment
|
19
|
-
!@\#{$%?&*()}
|
20
|
-
%>
|
21
|
-
EOF
|
22
|
-
|
23
|
-
assert_predicate errors, :empty?
|
24
|
-
end
|
25
|
-
|
26
|
-
test "multi line erb comments in html attribute" do
|
27
|
-
errors = parse(<<-EOF).errors
|
28
|
-
<div title="
|
29
|
-
<%#
|
30
|
-
this is a comment right in the middle of an attribute for some reason
|
31
|
-
%>
|
32
|
-
">
|
33
|
-
EOF
|
34
|
-
|
35
|
-
assert_predicate errors, :empty?
|
36
|
-
end
|
37
|
-
|
38
|
-
test "string without interpolation is safe" do
|
39
|
-
errors = parse(<<-EOF).errors
|
40
|
-
<a onclick="alert('<%= "something" %>')">
|
41
|
-
EOF
|
42
|
-
|
43
|
-
assert_equal 0, errors.size
|
44
|
-
end
|
45
|
-
|
46
|
-
test "string with interpolation" do
|
47
|
-
errors = parse(<<-EOF).errors
|
48
|
-
<a onclick="<%= "hello \#{name}" %>">
|
49
|
-
EOF
|
50
|
-
|
51
|
-
assert_equal 1, errors.size
|
52
|
-
assert_equal '"hello #{name}"', errors.first.location.source
|
53
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
54
|
-
end
|
55
|
-
|
56
|
-
test "string with interpolation and ternary" do
|
57
|
-
errors = parse(<<-EOF).errors
|
58
|
-
<a onclick="<%= "hello \#{foo ? bar : baz}" if bla? %>">
|
59
|
-
EOF
|
60
|
-
|
61
|
-
assert_equal 2, errors.size
|
62
|
-
|
63
|
-
assert_equal '"hello #{foo ? bar : baz}" if bla?', errors.first.location.source
|
64
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
65
|
-
|
66
|
-
assert_equal '"hello #{foo ? bar : baz}" if bla?', errors.first.location.source
|
67
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
68
|
-
end
|
69
|
-
|
70
|
-
test "plain erb tag in html attribute" do
|
71
|
-
errors = parse(<<-EOF).errors
|
72
|
-
<a onclick="method(<%= unsafe %>)">
|
73
|
-
EOF
|
74
|
-
|
75
|
-
assert_equal 1, errors.size
|
76
|
-
assert_equal 'unsafe', errors.first.location.source
|
77
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
78
|
-
end
|
79
|
-
|
80
|
-
test "to_json is safe in html attribute" do
|
81
|
-
errors = parse(<<-EOF).errors
|
82
|
-
<a onclick="method(<%= unsafe.to_json %>)">
|
83
|
-
EOF
|
84
|
-
assert_predicate errors, :empty?
|
85
|
-
end
|
86
|
-
|
87
|
-
test "ternary with safe javascript escaping" do
|
88
|
-
errors = parse(<<-EOF).errors
|
89
|
-
<a onclick="method(<%= foo ? bar.to_json : j(baz) %>)">
|
90
|
-
EOF
|
91
|
-
assert_predicate errors, :empty?
|
92
|
-
end
|
93
|
-
|
94
|
-
test "ternary with unsafe javascript escaping" do
|
95
|
-
errors = parse(<<-EOF).errors
|
96
|
-
<a onclick="method(<%= foo ? bar : j(baz) %>)">
|
97
|
-
EOF
|
98
|
-
|
99
|
-
assert_equal 1, errors.size
|
100
|
-
assert_equal 'foo ? bar : j(baz)', errors.first.location.source
|
101
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
102
|
-
end
|
103
|
-
|
104
|
-
test "j is safe in html attribute" do
|
105
|
-
errors = parse(<<-EOF).errors
|
106
|
-
<a onclick="method('<%= j unsafe %>')">
|
107
|
-
EOF
|
108
|
-
assert_predicate errors, :empty?
|
109
|
-
end
|
110
|
-
|
111
|
-
test "j() is safe in html attribute" do
|
112
|
-
errors = parse(<<-EOF).errors
|
113
|
-
<a onclick="method('<%= j(unsafe) %>')">
|
114
|
-
EOF
|
115
|
-
assert_predicate errors, :empty?
|
116
|
-
end
|
117
|
-
|
118
|
-
test "escape_javascript is safe in html attribute" do
|
119
|
-
errors = parse(<<-EOF).errors
|
120
|
-
<a onclick="method(<%= escape_javascript unsafe %>)">
|
121
|
-
EOF
|
122
|
-
assert_predicate errors, :empty?
|
123
|
-
end
|
124
|
-
|
125
|
-
test "escape_javascript() is safe in html attribute" do
|
126
|
-
errors = parse(<<-EOF).errors
|
127
|
-
<a onclick="method(<%= escape_javascript(unsafe) %>)">
|
128
|
-
EOF
|
129
|
-
assert_predicate errors, :empty?
|
130
|
-
end
|
131
|
-
|
132
|
-
test "html_safe is never safe in html attribute, even non javascript attributes like href" do
|
133
|
-
errors = parse(<<-EOF).errors
|
134
|
-
<a href="<%= unsafe.html_safe %>">
|
135
|
-
EOF
|
136
|
-
|
137
|
-
assert_equal 1, errors.size
|
138
|
-
assert_equal 'unsafe.html_safe', errors.first.location.source
|
139
|
-
assert_equal "erb interpolation with '<%= (...).html_safe %>' inside html attribute is never safe", errors.first.message
|
140
|
-
end
|
141
|
-
|
142
|
-
test "html_safe is never safe in html attribute, even with to_json" do
|
143
|
-
errors = parse(<<-EOF).errors
|
144
|
-
<a onclick="method(<%= unsafe.to_json.html_safe %>)">
|
145
|
-
EOF
|
146
|
-
|
147
|
-
assert_equal 1, errors.size
|
148
|
-
assert_equal 'unsafe.to_json.html_safe', errors.first.location.source
|
149
|
-
assert_equal "erb interpolation with '<%= (...).html_safe %>' inside html attribute is never safe", errors.first.message
|
150
|
-
end
|
151
|
-
|
152
|
-
test "<%== is never safe in html attribute, even non javascript attributes like href" do
|
153
|
-
errors = parse(<<-EOF).errors
|
154
|
-
<a href="<%== unsafe %>">
|
155
|
-
EOF
|
156
|
-
|
157
|
-
assert_equal 1, errors.size
|
158
|
-
assert_equal '<%== unsafe %>', errors.first.location.source
|
159
|
-
assert_includes "erb interpolation with '<%==' inside html attribute is never safe", errors.first.message
|
160
|
-
end
|
161
|
-
|
162
|
-
test "<%== is never safe in html attribute, even with to_json" do
|
163
|
-
errors = parse(<<-EOF).errors
|
164
|
-
<a onclick="method(<%== unsafe.to_json %>)">
|
165
|
-
EOF
|
166
|
-
|
167
|
-
assert_equal 1, errors.size
|
168
|
-
assert_equal '<%== unsafe.to_json %>', errors.first.location.source
|
169
|
-
assert_includes "erb interpolation with '<%==' inside html attribute is never safe", errors.first.message
|
170
|
-
end
|
171
|
-
|
172
|
-
test "raw is never safe in html attribute, even non javascript attributes like href" do
|
173
|
-
errors = parse(<<-EOF).errors
|
174
|
-
<a href="<%= raw unsafe %>">
|
175
|
-
EOF
|
176
|
-
|
177
|
-
assert_equal 1, errors.size
|
178
|
-
assert_equal 'raw unsafe', errors.first.location.source
|
179
|
-
assert_equal "erb interpolation with '<%= raw(...) %>' inside html attribute is never safe", errors.first.message
|
180
|
-
end
|
181
|
-
|
182
|
-
test "raw is never safe in html attribute, even with to_json" do
|
183
|
-
errors = parse(<<-EOF).errors
|
184
|
-
<a onclick="method(<%= raw unsafe.to_json %>)">
|
185
|
-
EOF
|
186
|
-
|
187
|
-
assert_equal 1, errors.size
|
188
|
-
assert_equal 'raw unsafe.to_json', errors.first.location.source
|
189
|
-
assert_equal "erb interpolation with '<%= raw(...) %>' inside html attribute is never safe", errors.first.message
|
190
|
-
end
|
191
|
-
|
192
|
-
test "unsafe erb in <script> tag without type" do
|
193
|
-
errors = parse(<<-EOF).errors
|
194
|
-
<script>
|
195
|
-
if (a < 1) { <%= unsafe %> }
|
196
|
-
</script>
|
197
|
-
EOF
|
198
|
-
|
199
|
-
assert_equal 1, errors.size
|
200
|
-
assert_equal '<%= unsafe %>', errors.first.location.source
|
201
|
-
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
202
|
-
end
|
203
|
-
|
204
|
-
test "unsafe erb in javascript template" do
|
205
|
-
errors = parse(<<-JS, template_language: :javascript).errors
|
206
|
-
if (a < 1) { <%= unsafe %> }
|
207
|
-
JS
|
208
|
-
|
209
|
-
assert_equal 1, errors.size
|
210
|
-
assert_equal '<%= unsafe %>', errors.first.location.source
|
211
|
-
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
212
|
-
end
|
213
|
-
|
214
|
-
test "<script> tag without calls is unsafe" do
|
215
|
-
errors = parse(<<-EOF).errors
|
216
|
-
<script type="text/javascript">
|
217
|
-
if (a < 1) { <%= "unsafe" %> }
|
218
|
-
</script>
|
219
|
-
EOF
|
220
|
-
|
221
|
-
assert_equal 1, errors.size
|
222
|
-
assert_equal '<%= "unsafe" %>', errors.first.location.source
|
223
|
-
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
224
|
-
end
|
225
|
-
|
226
|
-
test "javascript template without calls is unsafe" do
|
227
|
-
errors = parse(<<-JS, template_language: :javascript).errors
|
228
|
-
if (a < 1) { <%= "unsafe" %> }
|
229
|
-
JS
|
230
|
-
|
231
|
-
assert_equal 1, errors.size
|
232
|
-
assert_equal '<%= "unsafe" %>', errors.first.location.source
|
233
|
-
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
234
|
-
end
|
235
|
-
|
236
|
-
test "unsafe erb in javascript_tag" do
|
237
|
-
errors = parse(<<-EOF).errors
|
238
|
-
<%= javascript_tag do %>
|
239
|
-
if (a < 1) { <%= unsafe %> }
|
240
|
-
<% end %>
|
241
|
-
EOF
|
242
|
-
|
243
|
-
assert_equal 1, errors.size
|
244
|
-
assert_equal '<%= javascript_tag do %>', errors.first.location.source
|
245
|
-
assert_includes "'javascript_tag do' syntax is deprecated; use inline <script> instead", errors.first.message
|
246
|
-
end
|
247
|
-
|
248
|
-
test "unsafe erb in <script> tag with text/javascript content type" do
|
249
|
-
errors = parse(<<-EOF).errors
|
250
|
-
<script type="text/javascript">
|
251
|
-
if (a < 1) { <%= unsafe %> }
|
252
|
-
</script>
|
253
|
-
EOF
|
254
|
-
|
255
|
-
assert_equal 1, errors.size
|
256
|
-
assert_equal '<%= unsafe %>', errors.first.location.source
|
257
|
-
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
258
|
-
end
|
259
|
-
|
260
|
-
test "<script> tag with non executable content type is ignored" do
|
261
|
-
errors = parse(<<-EOF).errors
|
262
|
-
<script type="text/html">
|
263
|
-
<a onclick="<%= unsafe %>">
|
264
|
-
</script>
|
265
|
-
EOF
|
266
|
-
|
267
|
-
assert_predicate errors, :empty?
|
268
|
-
end
|
269
|
-
|
270
|
-
test "statements not allowed in script tags" do
|
271
|
-
errors = parse(<<-EOF).errors
|
272
|
-
<script type="text/javascript">
|
273
|
-
<% if foo? %>
|
274
|
-
bla
|
275
|
-
<% end %>
|
276
|
-
</script>
|
277
|
-
EOF
|
278
|
-
|
279
|
-
assert_equal 1, errors.size
|
280
|
-
assert_equal "<% if foo? %>", errors.first.location.source
|
281
|
-
assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
|
282
|
-
end
|
283
|
-
|
284
|
-
test "disallowed script types" do
|
285
|
-
errors = parse(<<-EOF).errors
|
286
|
-
<script type="text/bogus">
|
287
|
-
</script>
|
288
|
-
EOF
|
289
|
-
|
290
|
-
assert_equal 1, errors.size
|
291
|
-
assert_equal 'type="text/bogus"', errors.first.location.source
|
292
|
-
assert_equal "text/bogus is not a valid type, valid types are text/javascript, text/template, text/html", errors.first.message
|
293
|
-
end
|
294
|
-
|
295
|
-
test "statements not allowed in javascript template" do
|
296
|
-
errors = parse(<<-JS, template_language: :javascript).errors
|
297
|
-
<% if foo %>
|
298
|
-
bla
|
299
|
-
<% end %>
|
300
|
-
JS
|
301
|
-
|
302
|
-
assert_equal 1, errors.size
|
303
|
-
assert_equal "<% if foo %>", errors.first.location.source
|
304
|
-
assert_equal "erb statement not allowed here; did you mean '<%=' ?", errors.first.message
|
305
|
-
end
|
306
|
-
|
307
|
-
test "erb comments allowed in scripts" do
|
308
|
-
errors = parse(<<-EOF).errors
|
309
|
-
<script type="text/javascript">
|
310
|
-
<%# comment %>
|
311
|
-
</script>
|
312
|
-
EOF
|
313
|
-
|
314
|
-
assert_predicate errors, :empty?
|
315
|
-
end
|
316
|
-
|
317
|
-
test "script tag without content" do
|
318
|
-
errors = parse(<<-EOF).errors
|
319
|
-
<script type="text/javascript"></script>
|
320
|
-
EOF
|
321
|
-
|
322
|
-
assert_predicate errors, :empty?
|
323
|
-
end
|
324
|
-
|
325
|
-
test "statement after script regression" do
|
326
|
-
errors = parse(<<-EOF).errors
|
327
|
-
<script type="text/javascript">
|
328
|
-
foo()
|
329
|
-
</script>
|
330
|
-
<% if condition? %>
|
331
|
-
EOF
|
332
|
-
|
333
|
-
assert_predicate errors, :empty?
|
334
|
-
end
|
335
|
-
|
336
|
-
test "<script> with to_json is safe" do
|
337
|
-
errors = parse(<<-EOF).errors
|
338
|
-
<script type="text/javascript">
|
339
|
-
<%= unsafe.to_json %>
|
340
|
-
</script>
|
341
|
-
EOF
|
342
|
-
|
343
|
-
assert_predicate errors, :empty?
|
344
|
-
end
|
345
|
-
|
346
|
-
test "javascript template with to_json is safe" do
|
347
|
-
errors = parse(<<-JS, template_language: :javascript).errors
|
348
|
-
<%= unsafe.to_json %>
|
349
|
-
JS
|
350
|
-
|
351
|
-
assert_predicate errors, :empty?
|
352
|
-
end
|
353
|
-
|
354
|
-
test "<script> with raw and to_json is safe" do
|
355
|
-
errors = parse(<<-EOF).errors
|
356
|
-
<script type="text/javascript">
|
357
|
-
<%= raw unsafe.to_json %>
|
358
|
-
</script>
|
359
|
-
EOF
|
360
|
-
|
361
|
-
assert_predicate errors, :empty?
|
362
|
-
end
|
363
|
-
|
364
|
-
test "javascript template with raw and to_json is safe" do
|
365
|
-
errors = parse(<<-JS, template_language: :javascript).errors
|
366
|
-
<%= raw unsafe.to_json %>
|
367
|
-
JS
|
368
|
-
|
369
|
-
assert_predicate errors, :empty?
|
370
|
-
end
|
371
|
-
|
372
|
-
test "end statements are allowed in script tags" do
|
373
|
-
errors = parse(<<-EOF).errors
|
374
|
-
<script type="text/template">
|
375
|
-
<%= ui_form do %>
|
376
|
-
<div></div>
|
377
|
-
<% end %>
|
378
|
-
</script>
|
379
|
-
EOF
|
380
|
-
|
381
|
-
assert_predicate errors, :empty?
|
382
|
-
end
|
383
|
-
|
384
|
-
test "statements are allowed in text/html tags" do
|
385
|
-
errors = parse(<<-EOF).errors
|
386
|
-
<script type="text/html">
|
387
|
-
<% if condition? %>
|
388
|
-
<div></div>
|
389
|
-
<% end %>
|
390
|
-
</script>
|
391
|
-
EOF
|
392
|
-
|
393
|
-
assert_predicate errors, :empty?
|
394
|
-
end
|
395
|
-
|
396
|
-
test "unsafe javascript methods in helper calls with new hash syntax" do
|
397
|
-
errors = parse(<<-EOF).errors
|
398
|
-
<%= ui_my_helper(:foo, onclick: "alert(\#{unsafe})", onmouseover: "alert(\#{unsafe.to_json})") %>
|
399
|
-
EOF
|
400
|
-
|
401
|
-
assert_equal 1, errors.size
|
402
|
-
assert_equal "\#{unsafe}", errors[0].location.source
|
403
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors[0].message
|
404
|
-
end
|
405
|
-
|
406
|
-
test "unsafe javascript methods in helper calls with old hash syntax" do
|
407
|
-
errors = parse(<<-EOF).errors
|
408
|
-
<%= ui_my_helper(:foo, :onclick => "alert(\#{unsafe})") %>
|
409
|
-
EOF
|
410
|
-
|
411
|
-
assert_equal 1, errors.size
|
412
|
-
assert_equal "\#{unsafe}", errors.first.location.source
|
413
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
414
|
-
end
|
415
|
-
|
416
|
-
test "unsafe javascript methods in helper calls with string as key" do
|
417
|
-
errors = parse(<<-EOF).errors
|
418
|
-
<%= ui_my_helper(:foo, 'data-eval' => "alert(\#{unsafe})") %>
|
419
|
-
EOF
|
420
|
-
|
421
|
-
assert_equal 1, errors.size
|
422
|
-
assert_equal "\#{unsafe}", errors.first.location.source
|
423
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
424
|
-
end
|
425
|
-
|
426
|
-
test "unsafe javascript methods in helper calls with nested data key" do
|
427
|
-
errors = parse(<<-EOF).errors
|
428
|
-
<%= ui_my_helper(:foo, data: { eval: "alert(\#{unsafe})" }) %>
|
429
|
-
EOF
|
430
|
-
|
431
|
-
assert_equal 1, errors.size
|
432
|
-
assert_equal "\#{unsafe}", errors.first.location.source
|
433
|
-
assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
|
434
|
-
end
|
435
|
-
|
436
|
-
test "ivar missing .to_json is unsafe" do
|
437
|
-
errors = parse('<script><%= @feature.html_safe %></script>').errors
|
438
|
-
|
439
|
-
assert_equal 1, errors.size
|
440
|
-
assert_equal "<%= @feature.html_safe %>", errors.first.location.source
|
441
|
-
assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
|
442
|
-
end
|
443
|
-
|
444
|
-
private
|
445
|
-
def parse(data, template_language: :html)
|
446
|
-
SafeErbTester::Tester.new(data, config: @config, template_language: template_language)
|
447
|
-
end
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|