rufus-treechecker 1.0 → 1.0.1
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.
- data/lib/rufus/treechecker.rb +75 -24
- data/test/ft_0_basic.rb +22 -3
- data/test/ft_1_old_treechecker.rb +3 -3
- metadata +1 -1
data/lib/rufus/treechecker.rb
CHANGED
@@ -82,9 +82,10 @@ module Rufus
|
|
82
82
|
# - exclude_fcall
|
83
83
|
# - exclude_vcall
|
84
84
|
# - exclude_fvcall
|
85
|
-
# -
|
85
|
+
# - exclude_fvccall
|
86
86
|
# - exclude_call_on
|
87
87
|
# - exclude_call_to
|
88
|
+
# - exclude_rebinding
|
88
89
|
# - exclude_def
|
89
90
|
# - exclude_class_tinkering
|
90
91
|
# - exclude_module_tinkering
|
@@ -95,6 +96,7 @@ module Rufus
|
|
95
96
|
#
|
96
97
|
# Those rules take no arguments
|
97
98
|
#
|
99
|
+
# - exclude_access_to : prevents calling or rebinding a list of classes
|
98
100
|
# - exclude_eval : bans eval, module_eval and instance_eval
|
99
101
|
# - exclude_global_vars : bans calling or modifying global vars
|
100
102
|
# - exclude_alias : bans calls to alias and alias_method
|
@@ -123,7 +125,7 @@ module Rufus
|
|
123
125
|
#
|
124
126
|
class TreeChecker
|
125
127
|
|
126
|
-
VERSION = '1.0'
|
128
|
+
VERSION = '1.0.1'
|
127
129
|
|
128
130
|
#
|
129
131
|
# pretty-prints the sexp tree of the given rubycode
|
@@ -209,9 +211,9 @@ module Rufus
|
|
209
211
|
# Here is how it's built :
|
210
212
|
#
|
211
213
|
# return TreeChecker.new do
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
214
|
+
# exclude_fvccall :abort
|
215
|
+
# exclude_fvccall :exit, :exit!
|
216
|
+
# exclude_fvccall :system
|
215
217
|
# exclude_eval
|
216
218
|
# exclude_alias
|
217
219
|
# exclude_global_vars
|
@@ -223,9 +225,9 @@ module Rufus
|
|
223
225
|
def self.new_classic_tree_checker
|
224
226
|
|
225
227
|
return TreeChecker.new do
|
226
|
-
|
227
|
-
|
228
|
-
|
228
|
+
exclude_fvccall :abort
|
229
|
+
exclude_fvccall :exit, :exit!
|
230
|
+
exclude_fvccall :system
|
229
231
|
exclude_eval
|
230
232
|
exclude_alias
|
231
233
|
exclude_global_vars
|
@@ -272,7 +274,7 @@ module Rufus
|
|
272
274
|
:exclude_fcall,
|
273
275
|
:exclude_vcall,
|
274
276
|
:exclude_fvcall,
|
275
|
-
:
|
277
|
+
:exclude_fvccall,
|
276
278
|
:exclude_call_on,
|
277
279
|
:exclude_call_to
|
278
280
|
|
@@ -293,6 +295,38 @@ module Rufus
|
|
293
295
|
EOS
|
294
296
|
end
|
295
297
|
|
298
|
+
#
|
299
|
+
# This rule :
|
300
|
+
#
|
301
|
+
# exclude_rebinding Kernel
|
302
|
+
#
|
303
|
+
# will raise a security error for those pieces of code :
|
304
|
+
#
|
305
|
+
# k = Kernel
|
306
|
+
# k = ::Kernel
|
307
|
+
#
|
308
|
+
def exclude_rebinding (*args)
|
309
|
+
|
310
|
+
message = args.last.is_a?(String) ? args.pop : nil
|
311
|
+
|
312
|
+
args.each do |a|
|
313
|
+
c0 = parse(a.to_s)
|
314
|
+
c1 = parse("::#{a.to_s}")
|
315
|
+
@current_checks << [ :do_exclude_rebinding, c0, message ]
|
316
|
+
@current_checks << [ :do_exclude_rebinding, c1, message ]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
#
|
321
|
+
# prevents access (calling methods and rebinding) to a class (or a list
|
322
|
+
# of classes
|
323
|
+
#
|
324
|
+
def exclude_access_to (*args)
|
325
|
+
|
326
|
+
exclude_call_on *args
|
327
|
+
exclude_rebinding *args
|
328
|
+
end
|
329
|
+
|
296
330
|
#
|
297
331
|
# bans method definitions
|
298
332
|
#
|
@@ -391,8 +425,8 @@ module Rufus
|
|
391
425
|
#
|
392
426
|
def exclude_raise
|
393
427
|
|
394
|
-
@current_checks << [ :
|
395
|
-
@current_checks << [ :
|
428
|
+
@current_checks << [ :do_exclude_fvccall, :raise, "raise is forbidden" ]
|
429
|
+
@current_checks << [ :do_exclude_fvccall, :throw, "throw is forbidden" ]
|
396
430
|
end
|
397
431
|
|
398
432
|
#
|
@@ -447,12 +481,13 @@ module Rufus
|
|
447
481
|
end
|
448
482
|
|
449
483
|
#
|
450
|
-
# excludes :fcall and :vcall and :call
|
484
|
+
# excludes :fcall and :vcall and :call (to)
|
451
485
|
#
|
452
|
-
def
|
486
|
+
def do_exclude_fvccall (sexp, args)
|
453
487
|
|
454
488
|
do_exclude_fvcall(sexp, args)
|
455
|
-
do_exclude_head(sexp, cons([ :call, [ :const, :Kernel ] ], args))
|
489
|
+
#do_exclude_head(sexp, cons([ :call, [ :const, :Kernel ] ], args))
|
490
|
+
do_exclude_call_to(sexp, args)
|
456
491
|
end
|
457
492
|
|
458
493
|
#
|
@@ -475,28 +510,44 @@ module Rufus
|
|
475
510
|
do_exclude_head(sexp, [ [:call, args[0]] ] + (args[1, -1] || []))
|
476
511
|
end
|
477
512
|
|
513
|
+
#
|
514
|
+
# this method is called by all the methods checking composite sexps.
|
515
|
+
#
|
516
|
+
def do__exclude (sexp, args, default_error_message, &block)
|
517
|
+
|
518
|
+
return unless sexp.is_a?(Array)
|
519
|
+
|
520
|
+
raise SecurityError.new(
|
521
|
+
args[1] || default_error_message
|
522
|
+
) if block.call(args)
|
523
|
+
end
|
524
|
+
|
478
525
|
#
|
479
526
|
# raises a security error if a call to a given method of any instance
|
480
527
|
# is found
|
481
528
|
#
|
482
529
|
def do_exclude_call_to (sexp, args)
|
483
530
|
|
484
|
-
|
531
|
+
do__exclude(sexp, args, "calls to '#{args[0]}' are forbidden") do
|
485
532
|
|
486
|
-
|
487
|
-
|
488
|
-
) if sexp[0] == :call and sexp[2] == args[0]
|
533
|
+
(sexp[0] == :call and sexp[2] == args[0])
|
534
|
+
end
|
489
535
|
end
|
490
536
|
|
491
|
-
def
|
537
|
+
def do_exclude_rebinding (sexp, args)
|
492
538
|
|
493
|
-
|
539
|
+
do__exclude(sexp, args, "rebinding '#{args[0]}' is forbidden") do
|
494
540
|
|
495
|
-
|
541
|
+
(sexp[0] == :lasgn and sexp[2] == args[0])
|
542
|
+
end
|
543
|
+
end
|
496
544
|
|
497
|
-
|
498
|
-
|
499
|
-
|
545
|
+
def do_exclude_head (sexp, args)
|
546
|
+
|
547
|
+
do__exclude(sexp, args, "#{args[0].inspect} is forbidden") do
|
548
|
+
|
549
|
+
(sexp[0, args[0].length] == args[0])
|
550
|
+
end
|
500
551
|
end
|
501
552
|
|
502
553
|
def do_exclude_class_tinkering (sexp, args)
|
data/test/ft_0_basic.rb
CHANGED
@@ -218,10 +218,29 @@ class BasicTest < Test::Unit::TestCase
|
|
218
218
|
assert_ok(tc, 'lambda { a = 2 }')
|
219
219
|
end
|
220
220
|
|
221
|
-
def
|
221
|
+
def test_12_rebinding
|
222
222
|
|
223
|
-
|
224
|
-
|
223
|
+
tc = Rufus::TreeChecker.new do
|
224
|
+
exclude_call_to :class
|
225
|
+
exclude_rebinding Kernel, Rufus::TreeChecker
|
226
|
+
end
|
227
|
+
|
228
|
+
assert_nok(tc, 'k = Kernel')
|
229
|
+
assert_nok(tc, 'k = ::Kernel')
|
230
|
+
assert_nok(tc, 'c = Rufus::TreeChecker')
|
231
|
+
assert_nok(tc, 'c = ::Rufus::TreeChecker')
|
232
|
+
assert_nok(tc, 's = "".class')
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_13_access_to
|
236
|
+
|
237
|
+
tc = Rufus::TreeChecker.new do
|
238
|
+
exclude_access_to File
|
239
|
+
end
|
240
|
+
|
241
|
+
assert_nok(tc, 'f = File')
|
242
|
+
assert_nok(tc, 'f = ::File')
|
243
|
+
assert_nok(tc, 'File.read "hello.txt"')
|
225
244
|
end
|
226
245
|
|
227
246
|
#def test_X
|
@@ -21,9 +21,9 @@ class OldTreeCheckerTest < Test::Unit::TestCase
|
|
21
21
|
def test_0
|
22
22
|
|
23
23
|
tc = Rufus::TreeChecker.new do
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
exclude_fvccall :abort
|
25
|
+
exclude_fvccall :exit, :exit!
|
26
|
+
exclude_fvccall :system
|
27
27
|
exclude_eval
|
28
28
|
exclude_alias
|
29
29
|
exclude_global_vars
|