Class: Rufus::TreeChecker
- Inherits:
-
Object
- Object
- Rufus::TreeChecker
- Defined in:
- lib/rufus/treechecker.rb
Overview
TreeChecker relies on ruby_parser to turns a piece of ruby code (a string) into a bunch of sexpression and then TreeChecker will check that sexpression tree and raise a Rufus::SecurityException if an excluded pattern is spotted.
The TreeChecker is meant to be useful for people writing DSLs directly in Ruby (not via their own parser) that want to check and prevent bad things from happening in this code.
tc = Rufus::TreeChecker.new do
exclude_fvcall :abort
exclude_fvcall :exit, :exit!
end
tc.check("1 + 1; abort") # will raise a SecurityError
tc.check("puts (1..10).to_a.inspect") # OK
featured exclusion methods
call / vcall / fcall ?
What the difference between those ? Well, here is how those various piece of code look like :
"exit" => [:vcall, :exit]
"Kernel.exit" => [:call, [:const, :Kernel], :exit]
"Kernel::exit" => [:call, [:const, :Kernel], :exit]
"k.exit" => [:call, [:vcall, :k], :exit]
"exit -1" => [:fcall, :exit, [:array, [:lit, -1]]]
Obviously :fcall could be labelled as “function call”, :call is a call on to some instance, while vcall might either be a variable dereference or a function call with no arguments.
low-level rules
-
exclude_symbol : bans the usage of a given symbol (very low-level,
mostly used by other rules
-
exclude_head
-
exclude_fcall
-
exclude_vcall
-
exclude_fvcall
-
exclude_fvccall
-
exclude_call_on
-
exclude_call_to
-
exclude_rebinding
-
exclude_def
-
exclude_class_tinkering
-
exclude_module_tinkering
-
at_root
higher level rules
Those rules take no arguments
-
exclude_access_to : prevents calling or rebinding a list of classes
-
exclude_eval : bans eval, module_eval and instance_eval
-
exclude_global_vars : bans calling or modifying global vars
-
exclude_alias : bans calls to alias and alias_method
-
exclude_vm_exiting : bans exit, abort, …
-
exclude_raise : bans calls to raise or throw
a bit further
It’s possible to clone a TreeChecker and to add some more rules to it :
tc0 = Rufus::TreeChecker.new do
#
# calls to eval, module_eval and instance_eval are not allowed
#
exclude_eval
end
tc1 = tc0.clone
tc1.add_rules do
#
# calls to any method on File and FileUtils classes are not allowed
#
exclude_call_on File, FileUtils
end
Defined Under Namespace
Classes: RuleSet
Constant Summary collapse
- VERSION =
'1.0.4'
Instance Method Summary collapse
-
#add_rules(&block) ⇒ Object
Adds a set of checks (rules) to this treechecker.
-
#check(rubycode) ⇒ Object
Performs the check on the given String of ruby code.
-
#clone ⇒ Object
Return a copy of this TreeChecker instance.
-
#freeze ⇒ Object
Freezes the treechecker instance “in depth”.
-
#initialize(&block) ⇒ TreeChecker
constructor
initializes the TreeChecker, expects a block.
-
#ptree(rubycode) ⇒ Object
pretty-prints the sexp tree of the given rubycode.
-
#stree(rubycode) ⇒ Object
returns the pretty-printed string of the given rubycode (thanks ruby_parser).
- #to_s ⇒ Object
Constructor Details
#initialize(&block) ⇒ TreeChecker
initializes the TreeChecker, expects a block
142 143 144 145 146 147 148 149 |
# File 'lib/rufus/treechecker.rb', line 142 def initialize(&block) @root_set = RuleSet.new @set = RuleSet.new @current_set = @set add_rules(&block) end |
Instance Method Details
#add_rules(&block) ⇒ Object
Adds a set of checks (rules) to this treechecker. Returns self.
187 188 189 190 191 192 |
# File 'lib/rufus/treechecker.rb', line 187 def add_rules(&block) instance_eval(&block) if block self end |
#check(rubycode) ⇒ Object
Performs the check on the given String of ruby code. Will raise a Rufus::SecurityError if there is something excluded by the rules specified at the initialization of the TreeChecker instance.
163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/rufus/treechecker.rb', line 163 def check(rubycode) sexp = parse(rubycode) #@root_checks.each do |meth, *args| # send meth, sexp, args #end @root_set.check(sexp) do_check(sexp) end |
#clone ⇒ Object
Return a copy of this TreeChecker instance
177 178 179 180 181 182 183 |
# File 'lib/rufus/treechecker.rb', line 177 def clone tc = TreeChecker.new tc.instance_variable_set(:@root_set, @root_set.clone) tc.instance_variable_set(:@set, @set.clone) tc end |
#freeze ⇒ Object
Freezes the treechecker instance “in depth”
196 197 198 199 200 |
# File 'lib/rufus/treechecker.rb', line 196 def freeze super @root_set.freeze @set.freeze end |
#ptree(rubycode) ⇒ Object
pretty-prints the sexp tree of the given rubycode
129 130 131 |
# File 'lib/rufus/treechecker.rb', line 129 def ptree(rubycode) puts stree(rubycode) end |
#stree(rubycode) ⇒ Object
returns the pretty-printed string of the given rubycode (thanks ruby_parser).
136 137 138 |
# File 'lib/rufus/treechecker.rb', line 136 def stree(rubycode) "#{rubycode.inspect}\n =>\n#{parse(rubycode).inspect}" end |
#to_s ⇒ Object
151 152 153 154 155 156 157 |
# File 'lib/rufus/treechecker.rb', line 151 def to_s s = "#{self.class} (#{self.object_id})\n" s << "root_set :\n" s << @root_set.to_s s << "set :\n" s << @set.to_s end |