# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true cs__scoped_require 'contrast/components/interface' module Contrast module Extension module Assess # This Module allows us to track calls to the BasicObject#eval method, # which violates the design of most methods we track in that we have to # apply the trigger in a custom patch over one of the generic triggers in # TriggerMethod. class EvalTrigger include Contrast::Components::Interface access_component :logging class << self def instance_eval_trigger_check obj, source, ret apply_trigger(obj, source, ret, 'BasicObject', :instance_eval) end def eval_trigger_check obj, source, ret, method apply_trigger(obj, source, ret, 'Module', method) end def apply_trigger obj, source, ret, clazz, method current_context = Contrast::Agent::REQUEST_TRACKER.current return unless current_context # Since we know this is the source of the trigger, we can do some # optimization here and return when it is not tracked return unless Contrast::Utils::Assess::TrackingUtil.tracked?(source) # source might not be all the args passed in, but it is the one we care # about. we could pass in all the args in the last param here if it # becomes an issue in rendering on TS Contrast::Agent::Assess::Policy::TriggerMethod.apply_eval_trigger( current_context, trigger_node(clazz, method), source, obj, ret, source) end def instrument_basic_object_track @_instrument_basic_object_track ||= begin cs__scoped_require 'cs__assess_basic_object/cs__assess_basic_object' true end rescue StandardError, LoadError => e logger.error('Error loading basic object track patch', e) false end def instrument_module_track @_instrument_module_track ||= begin cs__scoped_require 'cs__assess_module/cs__assess_module' true end rescue StandardError, LoadError => e logger.error('Error loading module track patch', e) false end private def trigger_node clazz, method triggers = Contrast::Agent::Assess::Policy::Policy.instance.triggers return unless triggers triggers.find { |node| node.class_name == clazz && node.method_name == method } end end end end end end