Class: RuboCop::Cop::RosettAi::UnsafeConstGet

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/rosett_ai/unsafe_const_get.rb

Overview

Flags const_get and constantize calls with non-literal arguments. Dynamic constant lookup with user input can lead to arbitrary class instantiation and code execution.

Safe patterns use frozen constant registries that map user input to allowed class names.

Examples:

# bad
Object.const_get(user_input)
Kernel.const_get(params[:class])
user_input.constantize

# good - use a frozen allowlist
ALLOWED_CLASSES = { 'foo' => Foo, 'bar' => Bar }.freeze
ALLOWED_CLASSES.fetch(user_input)

# good - literal constant names
Object.const_get(:MyClass)
Object.const_get('RosettAi::Parser')

Constant Summary collapse

MSG =
'Avoid `const_get` with non-literal arguments. ' \
'Use a frozen allowlist instead to prevent arbitrary class instantiation.'
CONSTANTIZE_MSG =
'Avoid `constantize` on dynamic strings. ' \
'Use a frozen allowlist instead.'
CONST_GET_METHODS =
[:const_get].freeze
CONSTANTIZE_METHODS =
[:constantize, :safe_constantize].freeze

Instance Method Summary collapse

Instance Method Details

#const_get_with_dynamic?(node) ⇒ Object

const_get with any argument that is not a literal symbol or string



40
41
42
# File 'lib/rubocop/cop/rosett_ai/unsafe_const_get.rb', line 40

def_node_matcher :const_get_with_dynamic?, <<~PATTERN
  (send _ {:const_get} $!{sym str})
PATTERN

#constantize_call?(node) ⇒ Object

.constantize or .safe_constantize on any receiver



46
47
48
# File 'lib/rubocop/cop/rosett_ai/unsafe_const_get.rb', line 46

def_node_matcher :constantize_call?, <<~PATTERN
  (send _ {:constantize :safe_constantize})
PATTERN

#on_send(node) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/rubocop/cop/rosett_ai/unsafe_const_get.rb', line 50

def on_send(node)
  if const_get_with_dynamic?(node)
    add_offense(node)
  elsif constantize_call?(node)
    add_offense(node, message: CONSTANTIZE_MSG)
  end
end