Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEV: import code from unmaintained ruby gem safe_ruby to local library #93

Merged
merged 6 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/discourse_chatbot/functions/calculator_function.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def process(args)
begin
super(args)

SafeRuby.eval(args[parameters[0][:name]], timeout: 5)
::SafeRuby.eval(args[parameters[0][:name]], timeout: 5)
rescue
I18n.t("chatbot.prompt.function.calculator.error", parameter: args[parameters[0][:name]])
end
Expand Down
15 changes: 15 additions & 0 deletions lib/discourse_chatbot/safe_ruby/lib/constant_whitelist.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

ALLOWED_CONSTANTS= [
:Object, :Module, :Class, :BasicObject, :Kernel, :NilClass, :NIL, :Data, :TrueClass, :TRUE, :FalseClass, :FALSE, :Encoding,
:Comparable, :Enumerable, :String, :Symbol, :Exception, :SystemExit, :SignalException, :Interrupt, :StandardError, :TypeError,
:ArgumentError, :IndexError, :KeyError, :RangeError, :ScriptError, :SyntaxError, :LoadError, :NotImplementedError, :NameError,
:NoMethodError, :RuntimeError, :SecurityError, :NoMemoryError, :EncodingError, :SystemCallError, :Errno, :ZeroDivisionError,
:FloatDomainError, :Numeric, :Integer, :Fixnum, :Float, :Bignum, :Array, :Hash, :Struct, :RegexpError, :Regexp,
:MatchData, :Marshal, :Range, :IOError, :EOFError, :IO, :STDIN, :STDOUT, :STDERR, :Time, :Random,
:Signal, :Proc, :LocalJumpError, :SystemStackError, :Method, :UnboundMethod, :Binding, :Math, :Enumerator,
:StopIteration, :RubyVM, :Thread, :TOPLEVEL_BINDING, :ThreadGroup, :Mutex, :ThreadError, :Fiber, :FiberError, :Rational, :Complex,
:RUBY_VERSION, :RUBY_RELEASE_DATE, :RUBY_PLATFORM, :RUBY_PATCHLEVEL, :RUBY_REVISION, :RUBY_DESCRIPTION, :RUBY_COPYRIGHT, :RUBY_ENGINE,
:TracePoint, :ARGV, :Gem, :RbConfig, :Config, :CROSS_COMPILING, :Date, :ConditionVariable, :Queue, :SizedQueue, :MonitorMixin, :Monitor,
:Exception2MessageMapper, :IRB, :RubyToken, :RubyLex, :Readline, :RUBYGEMS_ACTIVATION_MONITOR
]
53 changes: 53 additions & 0 deletions lib/discourse_chatbot/safe_ruby/lib/make_safe_code.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

MAKE_SAFE_CODE = <<-STRING
def keep_singleton_methods(klass, singleton_methods)
klass = Object.const_get(klass)
singleton_methods = singleton_methods.map(&:to_sym)
undef_methods = (klass.singleton_methods - singleton_methods)

undef_methods.each do |method|
klass.singleton_class.send(:undef_method, method)
end

end

def keep_methods(klass, methods)
klass = Object.const_get(klass)
methods = methods.map(&:to_sym)
undef_methods = (klass.methods(false) - methods)
undef_methods.each do |method|
klass.send(:undef_method, method)
end
end

def clean_constants
(Object.constants - #{ALLOWED_CONSTANTS}).each do |const|
Object.send(:remove_const, const) if defined?(const)
end
end

keep_singleton_methods(:Kernel, #{KERNEL_S_METHODS})
keep_singleton_methods(:Symbol, #{SYMBOL_S_METHODS})
keep_singleton_methods(:String, #{STRING_S_METHODS})
keep_singleton_methods(:IO, #{IO_S_METHODS})

keep_methods(:Kernel, #{KERNEL_METHODS})
keep_methods(:NilClass, #{NILCLASS_METHODS})
keep_methods(:TrueClass, #{TRUECLASS_METHODS})
keep_methods(:FalseClass, #{FALSECLASS_METHODS})
keep_methods(:Enumerable, #{ENUMERABLE_METHODS})
keep_methods(:String, #{STRING_METHODS})
Kernel.class_eval do
def `(*args)
raise NoMethodError, "` is unavailable"
end

def system(*args)
raise NoMethodError, "system is unavailable"
end
end

clean_constants

STRING
272 changes: 272 additions & 0 deletions lib/discourse_chatbot/safe_ruby/lib/method_whitelist.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
# frozen_string_literal: true

IO_S_METHODS = %w[
new
foreach
open
]

KERNEL_S_METHODS = %w[
Array
binding
block_given?
catch
chomp
chomp!
chop
chop!
eval
fail
Float
format
global_variables
gsub
gsub!
Integer
iterator?
lambda
local_variables
loop
method_missing
proc
raise
scan
split
sprintf
String
sub
sub!
throw
].freeze

SYMBOL_S_METHODS = %w[
all_symbols
].freeze

STRING_S_METHODS = %w[
].freeze

KERNEL_METHODS = %w[
==

ray
nding
ock_given?
tch
omp
omp!
op
op!
ass
clone
dup
eql?
equal?
eval
fail
Float
format
freeze
frozen?
global_variables
gsub
gsub!
hash
id
initialize_copy
inspect
instance_eval
instance_of?
instance_variables
instance_variable_get
instance_variable_set
instance_variable_defined?
Integer
is_a?
iterator?
kind_of?
lambda
local_variables
loop
methods
method_missing
nil?
private_methods
print
proc
protected_methods
public_methods
raise
remove_instance_variable
respond_to?
respond_to_missing?
scan
send
singleton_methods
singleton_method_added
singleton_method_removed
singleton_method_undefined
split
sprintf
String
sub
sub!
taint
tainted?
throw
to_a
to_s
type
untaint
__send__
].freeze

NILCLASS_METHODS = %w[
&
inspect
nil?
to_a
to_f
to_i
to_s
^
|
].freeze

SYMBOL_METHODS = %w[
===
id2name
inspect
to_i
to_int
to_s
to_sym
].freeze

TRUECLASS_METHODS = %w[
&
to_s
^
|
].freeze

FALSECLASS_METHODS = %w[
&
to_s
^
|
].freeze

ENUMERABLE_METHODS = %w[
all?
any?
collect
detect
each_with_index
entries
find
find_all
grep
include?
inject
map
max
member?
min
partition
reject
select
sort
sort_by
to_a
zip
].freeze

STRING_METHODS = %w[
%
*
+
<<
<=>
==
=~
capitalize
capitalize!
casecmp
center
chomp
chomp!
chop
chop!
concat
count
crypt
delete
delete!
downcase
downcase!
dump
each
each_byte
each_line
empty?
eql?
gsub
gsub!
hash
hex
include?
index
initialize
initialize_copy
insert
inspect
intern
length
ljust
lines
lstrip
lstrip!
match
next
next!
oct
replace
reverse
reverse!
rindex
rjust
rstrip
rstrip!
scan
size
slice
slice!
split
squeeze
squeeze!
strip
strip!
start_with?
sub
sub!
succ
succ!
sum
swapcase
swapcase!
to_f
to_i
to_s
to_str
to_sym
tr
tr!
tr_s
tr_s!
upcase
upcase!
upto
[]
[]=
].freeze
11 changes: 11 additions & 0 deletions lib/discourse_chatbot/safe_ruby/lib/safe_ruby.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require 'childprocess'
require_relative 'method_whitelist'
require_relative 'constant_whitelist'
require_relative 'make_safe_code'
require_relative 'safe_ruby/runner'
require_relative 'safe_ruby/version'

class SafeRuby
end
Loading