safemode 1.5.0 → 1.6.0
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/demo.rb +2 -0
- data/lib/safemode/core_jails.rb +18 -21
- data/lib/safemode/parser.rb +2 -4
- data/lib/safemode.rb +0 -7
- data/safemode.gemspec +9 -9
- data/test/test_erb_eval.rb +4 -4
- data/test/test_helper.rb +2 -0
- data/test/test_jail.rb +2 -0
- data/test/test_safemode_eval.rb +26 -4
- data/test/test_safemode_parser.rb +2 -0
- metadata +32 -33
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60d02e15fb3d2ae2d1447e72e0c92e7379c826393b64349ce3c2c71ca4d53da5
|
|
4
|
+
data.tar.gz: 3cb324e0289157a132e5edd0535cc66d6ae351acf737b092d74a68859ebfe887
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 364354811cc8928d257da2d095e4aed8301eb5d26a7d2303d8f0be5e9d16a1c9172f04c967c385a31ea24af95dc6c2eb00ef2fd7eb47426872db0064a5035cd0
|
|
7
|
+
data.tar.gz: 01f78d9d81dffa08d50068177840324c7d54db94249a3714b34d2e2301386836a061c85da2ce4d610c8890f60427b76bb2fa3bb2f7e90a917a6c2316ff58c13b
|
data/demo.rb
CHANGED
data/lib/safemode/core_jails.rb
CHANGED
|
@@ -17,15 +17,11 @@ module Safemode
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def core_classes
|
|
20
|
-
klasses = [ Array, Float, Hash, Range, String, Symbol, Time, NilClass, FalseClass, TrueClass ]
|
|
20
|
+
klasses = [ Array, Float, Hash, Integer, Range, String, Symbol, Time, NilClass, FalseClass, TrueClass ]
|
|
21
21
|
klasses << Date if defined? Date
|
|
22
22
|
klasses << DateTime if defined? DateTime
|
|
23
|
-
if
|
|
24
|
-
|
|
25
|
-
else
|
|
26
|
-
klasses << Bignum
|
|
27
|
-
klasses << Fixnum
|
|
28
|
-
end
|
|
23
|
+
klasses << Data if defined? Data # Ruby 3.2 addition
|
|
24
|
+
klasses << Set if defined? Set # Ruby 3.2 addition
|
|
29
25
|
klasses
|
|
30
26
|
end
|
|
31
27
|
|
|
@@ -46,31 +42,21 @@ module Safemode
|
|
|
46
42
|
# whitelisted methods for core classes ... kind of arbitrary selection
|
|
47
43
|
@@methods_whitelist = {
|
|
48
44
|
'Array' => %w(any? assoc at blank? collect collect! compact compact!
|
|
49
|
-
concat delete delete_at delete_if each each_index
|
|
50
|
-
fetch fill first flatten flatten! hash include? index
|
|
45
|
+
concat delete delete_at delete_if each each_index each_with_index
|
|
46
|
+
empty? fetch fill first flatten flatten! hash include? index
|
|
51
47
|
indexes indices inject insert join last length map map! max min
|
|
52
48
|
nitems pop push present? rassoc reject reject! reverse
|
|
53
49
|
reverse! reverse_each rindex select shift size slice
|
|
54
50
|
slice! sort sort! transpose to_sentence uniq uniq! unshift
|
|
55
51
|
values_at zip),
|
|
56
52
|
|
|
57
|
-
'Bignum' => %w(abs blank? ceil chr coerce div divmod downto floor hash
|
|
58
|
-
integer? modulo next nonzero? present? quo remainder round
|
|
59
|
-
singleton_method_added size step succ times to_f to_i
|
|
60
|
-
to_int to_s truncate upto zero?),
|
|
61
|
-
|
|
62
|
-
'Fixnum' => %w(abs blank? ceil chr coerce div divmod downto floor id2name
|
|
63
|
-
integer? modulo modulo next nonzero? present? quo remainder
|
|
64
|
-
round singleton_method_added size step succ times to_f to_i
|
|
65
|
-
to_int to_s to_sym truncate upto zero?),
|
|
66
|
-
|
|
67
53
|
'Float' => %w(abs blank? ceil coerce div divmod finite? floor hash
|
|
68
54
|
infinite? integer? modulo nan? nonzero? present? quo
|
|
69
55
|
remainder round singleton_method_added step to_f to_i
|
|
70
56
|
to_int to_s truncate zero?),
|
|
71
57
|
|
|
72
|
-
'Hash' => %w(any? blank? clear delete delete_if each each_key
|
|
73
|
-
|
|
58
|
+
'Hash' => %w(any? blank? clear delete delete_if each each_key each_pair
|
|
59
|
+
each_value each_with_index empty? fetch dig has_key? has_value?
|
|
74
60
|
include? index invert key? keys length member? merge merge!
|
|
75
61
|
present? rec_merge! rehash reject reject! select shift
|
|
76
62
|
size sort store update value? values values_at),
|
|
@@ -116,6 +102,17 @@ module Safemode
|
|
|
116
102
|
'DateTime' => %w(blank? hour min new_offset newof of offset present? sec
|
|
117
103
|
sec_fraction strftime to_datetime_default_s to_json zone),
|
|
118
104
|
|
|
105
|
+
'Data' => %w(deconstruct deconstruct_keys hash members),
|
|
106
|
+
|
|
107
|
+
'Set' => %w(any? blank? clear clone collect count delete delete?
|
|
108
|
+
delete_if difference disjoint? each each_with_index
|
|
109
|
+
each_with_object empty? filter find first flatten
|
|
110
|
+
flatten! hash include? inject intersect? intersection
|
|
111
|
+
join keep_if length map max member? merge min
|
|
112
|
+
present? reject reject! replace select select!
|
|
113
|
+
size sort sort_by subset? superset? union
|
|
114
|
+
uniq zip),
|
|
115
|
+
|
|
119
116
|
'NilClass' => %w(blank? duplicable? present? to_f to_i),
|
|
120
117
|
|
|
121
118
|
'FalseClass' => %w(blank? duplicable? present?),
|
data/lib/safemode/parser.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
module Safemode
|
|
2
2
|
class Parser < Ruby2Ruby
|
|
3
|
-
# @@parser = defined?(RubyParser) ? 'RubyParser' : 'ParseTree'
|
|
4
3
|
@@parser = 'RubyParser'
|
|
5
4
|
|
|
6
5
|
class << self
|
|
@@ -12,8 +11,6 @@ module Safemode
|
|
|
12
11
|
|
|
13
12
|
def parse(code)
|
|
14
13
|
case @@parser
|
|
15
|
-
# when 'ParseTree'
|
|
16
|
-
# ParseTree.translate(code)
|
|
17
14
|
when 'RubyParser'
|
|
18
15
|
RubyParser.new.parse(code)
|
|
19
16
|
else
|
|
@@ -90,7 +87,8 @@ module Safemode
|
|
|
90
87
|
:colon2,
|
|
91
88
|
# unnecessarily advanced?
|
|
92
89
|
:argscat, :argspush, :splat,
|
|
93
|
-
:op_asgn1, :op_asgn2, :op_asgn_and, :op_asgn_or,
|
|
90
|
+
:op_asgn, :op_asgn1, :op_asgn2, :op_asgn_and, :op_asgn_or,
|
|
91
|
+
:safe_op_asgn,
|
|
94
92
|
# needed for haml
|
|
95
93
|
:block ]
|
|
96
94
|
|
data/lib/safemode.rb
CHANGED
|
@@ -5,13 +5,6 @@ begin
|
|
|
5
5
|
require 'ruby_parser' # try to load RubyParser and use it if present
|
|
6
6
|
rescue LoadError => e
|
|
7
7
|
end
|
|
8
|
-
# this doesn't work somehow. Maybe something changed inside
|
|
9
|
-
# ParseTree or sexp_processor or so.
|
|
10
|
-
# (the require itself works, but ParseTree doesn't play nice)
|
|
11
|
-
# begin
|
|
12
|
-
# require 'parse_tree'
|
|
13
|
-
# rescue LoadError => e
|
|
14
|
-
# end
|
|
15
8
|
|
|
16
9
|
require 'safemode/core_ext'
|
|
17
10
|
require 'safemode/blankslate'
|
data/safemode.gemspec
CHANGED
|
@@ -4,10 +4,10 @@ require 'date'
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |s|
|
|
6
6
|
s.name = "safemode".freeze
|
|
7
|
-
s.version = "1.
|
|
7
|
+
s.version = "1.6.0"
|
|
8
8
|
s.date = Date.today
|
|
9
9
|
|
|
10
|
-
s.summary = "A library for safe evaluation of Ruby code based on
|
|
10
|
+
s.summary = "A library for safe evaluation of Ruby code based on RubyParser and Ruby2Ruby"
|
|
11
11
|
s.description = "A library for safe evaluation of Ruby code based on RubyParser and Ruby2Ruby. Provides Rails ActionView template handlers for ERB and Haml."
|
|
12
12
|
s.homepage = "https://github.com/svenfuchs/safemode"
|
|
13
13
|
s.licenses = ["MIT"]
|
|
@@ -54,12 +54,12 @@ Gem::Specification.new do |s|
|
|
|
54
54
|
|
|
55
55
|
s.required_ruby_version = ">= 2.7", "< 3.2"
|
|
56
56
|
|
|
57
|
-
s.add_runtime_dependency "ruby2ruby", "
|
|
58
|
-
s.add_runtime_dependency "ruby_parser", "
|
|
59
|
-
s.add_runtime_dependency "sexp_processor", "
|
|
57
|
+
s.add_runtime_dependency "ruby2ruby", "~> 2.4"
|
|
58
|
+
s.add_runtime_dependency "ruby_parser", "~> 3.10"
|
|
59
|
+
s.add_runtime_dependency "sexp_processor", "~> 4.10"
|
|
60
60
|
|
|
61
|
-
s.add_development_dependency "rake"
|
|
62
|
-
s.add_development_dependency "rdoc"
|
|
63
|
-
s.add_development_dependency "simplecov"
|
|
64
|
-
s.add_development_dependency "test-unit"
|
|
61
|
+
s.add_development_dependency "rake", "~> 13.4"
|
|
62
|
+
s.add_development_dependency "rdoc", "~> 7.2"
|
|
63
|
+
s.add_development_dependency "simplecov", "~> 0.22"
|
|
64
|
+
s.add_development_dependency "test-unit", "~> 3.7"
|
|
65
65
|
end
|
data/test/test_erb_eval.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
|
2
4
|
|
|
3
5
|
class TestERBEval < Test::Unit::TestCase
|
|
@@ -58,19 +60,17 @@ class TestERBEval < Test::Unit::TestCase
|
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
TestHelper.no_method_error_raising_calls.each do |call|
|
|
61
|
-
call.gsub!('"', '\\\\"')
|
|
62
63
|
class_eval %Q(
|
|
63
64
|
def test_calling_#{call.gsub(/[\W]/, '_')}_should_raise_no_method
|
|
64
|
-
assert_raise_no_method "#{call}", @assigns, @locals
|
|
65
|
+
assert_raise_no_method "#{call.gsub('"', '\\\\"')}", @assigns, @locals
|
|
65
66
|
end
|
|
66
67
|
)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
TestHelper.security_error_raising_calls.each do |call|
|
|
70
|
-
call.gsub!('"', '\\\\"')
|
|
71
71
|
class_eval %Q(
|
|
72
72
|
def test_calling_#{call.gsub(/[\W]/, '_')}_should_raise_security
|
|
73
|
-
assert_raise_security "#{call}", @assigns, @locals
|
|
73
|
+
assert_raise_security "#{call.gsub('"', '\\\\"')}", @assigns, @locals
|
|
74
74
|
end
|
|
75
75
|
)
|
|
76
76
|
end
|
data/test/test_helper.rb
CHANGED
data/test/test_jail.rb
CHANGED
data/test/test_safemode_eval.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
|
2
4
|
|
|
3
5
|
class TestSafemodeEval < Test::Unit::TestCase
|
|
@@ -98,20 +100,40 @@ class TestSafemodeEval < Test::Unit::TestCase
|
|
|
98
100
|
end
|
|
99
101
|
end
|
|
100
102
|
|
|
103
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2')
|
|
104
|
+
def test_pattern_matching_with_data_subclass
|
|
105
|
+
point_class = Data.define(:x, :y)
|
|
106
|
+
point = point_class.new(x: 10, y: 20)
|
|
107
|
+
assert_equal 10, @box.eval('case @point; in {x:}; x; end', { point: point })
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_data_subclass_inherits_data_jail
|
|
111
|
+
point_class = Data.define(:x, :y)
|
|
112
|
+
point = point_class.new(x: 10, y: 20)
|
|
113
|
+
assert_equal [:x, :y], @box.eval('@point.members', { point: point })
|
|
114
|
+
assert_equal [10, 20], @box.eval('@point.deconstruct', { point: point })
|
|
115
|
+
assert_equal({ x: 10 }, @box.eval('@point.deconstruct_keys([:x])', { point: point }))
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_data_subclass_jail_blocks_non_whitelisted_methods
|
|
119
|
+
point_class = Data.define(:x, :y)
|
|
120
|
+
point = point_class.new(x: 10, y: 20)
|
|
121
|
+
assert_raise(Safemode::NoMethodError) { @box.eval('@point.instance_variables', { point: point }) }
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
101
125
|
TestHelper.no_method_error_raising_calls.each do |call|
|
|
102
|
-
call.gsub!('"', '\\\\"')
|
|
103
126
|
class_eval %Q(
|
|
104
127
|
def test_calling_#{call.gsub(/[\W]/, '_')}_should_raise_no_method
|
|
105
|
-
assert_raise_no_method "#{call}", @assigns, @locals
|
|
128
|
+
assert_raise_no_method "#{call.gsub('"', '\\\\"')}", @assigns, @locals
|
|
106
129
|
end
|
|
107
130
|
)
|
|
108
131
|
end
|
|
109
132
|
|
|
110
133
|
TestHelper.security_error_raising_calls.each do |call|
|
|
111
|
-
call.gsub!('"', '\\\\"')
|
|
112
134
|
class_eval %Q(
|
|
113
135
|
def test_calling_#{call.gsub(/[\W]/, '_')}_should_raise_security
|
|
114
|
-
assert_raise_security "#{call}", @assigns, @locals
|
|
136
|
+
assert_raise_security "#{call.gsub('"', '\\\\"')}", @assigns, @locals
|
|
115
137
|
end
|
|
116
138
|
)
|
|
117
139
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: safemode
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sven Fuchs
|
|
@@ -13,106 +13,106 @@ authors:
|
|
|
13
13
|
autorequire:
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
|
-
date:
|
|
16
|
+
date: 2026-05-21 00:00:00.000000000 Z
|
|
17
17
|
dependencies:
|
|
18
18
|
- !ruby/object:Gem::Dependency
|
|
19
19
|
name: ruby2ruby
|
|
20
20
|
requirement: !ruby/object:Gem::Requirement
|
|
21
21
|
requirements:
|
|
22
|
-
- - "
|
|
22
|
+
- - "~>"
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version: 2.4
|
|
24
|
+
version: '2.4'
|
|
25
25
|
type: :runtime
|
|
26
26
|
prerelease: false
|
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
|
28
28
|
requirements:
|
|
29
|
-
- - "
|
|
29
|
+
- - "~>"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
|
-
version: 2.4
|
|
31
|
+
version: '2.4'
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
33
|
name: ruby_parser
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
35
35
|
requirements:
|
|
36
|
-
- - "
|
|
36
|
+
- - "~>"
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: 3.10
|
|
38
|
+
version: '3.10'
|
|
39
39
|
type: :runtime
|
|
40
40
|
prerelease: false
|
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
|
42
42
|
requirements:
|
|
43
|
-
- - "
|
|
43
|
+
- - "~>"
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: 3.10
|
|
45
|
+
version: '3.10'
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
47
|
name: sexp_processor
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
49
49
|
requirements:
|
|
50
|
-
- - "
|
|
50
|
+
- - "~>"
|
|
51
51
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: 4.10
|
|
52
|
+
version: '4.10'
|
|
53
53
|
type: :runtime
|
|
54
54
|
prerelease: false
|
|
55
55
|
version_requirements: !ruby/object:Gem::Requirement
|
|
56
56
|
requirements:
|
|
57
|
-
- - "
|
|
57
|
+
- - "~>"
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 4.10
|
|
59
|
+
version: '4.10'
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: rake
|
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
|
63
63
|
requirements:
|
|
64
|
-
- - "
|
|
64
|
+
- - "~>"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: '
|
|
66
|
+
version: '13.4'
|
|
67
67
|
type: :development
|
|
68
68
|
prerelease: false
|
|
69
69
|
version_requirements: !ruby/object:Gem::Requirement
|
|
70
70
|
requirements:
|
|
71
|
-
- - "
|
|
71
|
+
- - "~>"
|
|
72
72
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: '
|
|
73
|
+
version: '13.4'
|
|
74
74
|
- !ruby/object:Gem::Dependency
|
|
75
75
|
name: rdoc
|
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
|
77
77
|
requirements:
|
|
78
|
-
- - "
|
|
78
|
+
- - "~>"
|
|
79
79
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: '
|
|
80
|
+
version: '7.2'
|
|
81
81
|
type: :development
|
|
82
82
|
prerelease: false
|
|
83
83
|
version_requirements: !ruby/object:Gem::Requirement
|
|
84
84
|
requirements:
|
|
85
|
-
- - "
|
|
85
|
+
- - "~>"
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
|
-
version: '
|
|
87
|
+
version: '7.2'
|
|
88
88
|
- !ruby/object:Gem::Dependency
|
|
89
89
|
name: simplecov
|
|
90
90
|
requirement: !ruby/object:Gem::Requirement
|
|
91
91
|
requirements:
|
|
92
|
-
- - "
|
|
92
|
+
- - "~>"
|
|
93
93
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: '0'
|
|
94
|
+
version: '0.22'
|
|
95
95
|
type: :development
|
|
96
96
|
prerelease: false
|
|
97
97
|
version_requirements: !ruby/object:Gem::Requirement
|
|
98
98
|
requirements:
|
|
99
|
-
- - "
|
|
99
|
+
- - "~>"
|
|
100
100
|
- !ruby/object:Gem::Version
|
|
101
|
-
version: '0'
|
|
101
|
+
version: '0.22'
|
|
102
102
|
- !ruby/object:Gem::Dependency
|
|
103
103
|
name: test-unit
|
|
104
104
|
requirement: !ruby/object:Gem::Requirement
|
|
105
105
|
requirements:
|
|
106
|
-
- - "
|
|
106
|
+
- - "~>"
|
|
107
107
|
- !ruby/object:Gem::Version
|
|
108
|
-
version: '
|
|
108
|
+
version: '3.7'
|
|
109
109
|
type: :development
|
|
110
110
|
prerelease: false
|
|
111
111
|
version_requirements: !ruby/object:Gem::Requirement
|
|
112
112
|
requirements:
|
|
113
|
-
- - "
|
|
113
|
+
- - "~>"
|
|
114
114
|
- !ruby/object:Gem::Version
|
|
115
|
-
version: '
|
|
115
|
+
version: '3.7'
|
|
116
116
|
description: A library for safe evaluation of Ruby code based on RubyParser and Ruby2Ruby.
|
|
117
117
|
Provides Rails ActionView template handlers for ERB and Haml.
|
|
118
118
|
email:
|
|
@@ -168,9 +168,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
168
168
|
- !ruby/object:Gem::Version
|
|
169
169
|
version: '0'
|
|
170
170
|
requirements: []
|
|
171
|
-
rubygems_version: 3.
|
|
171
|
+
rubygems_version: 3.2.33
|
|
172
172
|
signing_key:
|
|
173
173
|
specification_version: 4
|
|
174
|
-
summary: A library for safe evaluation of Ruby code based on
|
|
175
|
-
and Ruby2Ruby
|
|
174
|
+
summary: A library for safe evaluation of Ruby code based on RubyParser and Ruby2Ruby
|
|
176
175
|
test_files: []
|