# 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 Kernel # :nodoc: include Contrast::Components::Interface access_component :scope alias_method :cs__catch, :catch # In the event of a `throw`, we need to override `catch` # to save & restore scope state: # # scope_level == 0 # # catch(:abc) do # with_contrast_scope do # throw :abc # will leak # end # end # # scope_level == 1 # # While this will fix /all/ scope leaks, not just ones caused by `throw`, # it shouldn't be relied upon as a catch-all (lmao) solution. private def catch *args, &block # Save current scope level scope_level = SCOPE.scope_for_current_ec.instance_variable_get(:@contrast_scope) # Run original catch with block. retval = cs__catch(*args, &block) # Restore scope. SCOPE.scope_for_current_ec.instance_variable_set(:@contrast_scope, scope_level) retval end end # ScopeUtil should probably be merged into Scope component. module Contrast module Utils module ScopeUtil # :nodoc: include Contrast::Components::Interface access_component :analysis, :scope # @return [Boolean] def skip_contrast_analysis? return true if in_contrast_scope? return true unless Contrast::Agent::REQUEST_TRACKER.current&.analyze_request? false end # Skip if we should skip_contrast_analysis?, sampling says to ignore this # request, or assess has been disabled. # # @return [Boolean] def skip_assess_analysis? return true if skip_contrast_analysis? current_context = Contrast::Agent::REQUEST_TRACKER.current return true unless current_context.analyze_request? !ASSESS.enabled? end def cs__enter_scope enter_contrast_scope! end def cs__leave_scope exit_contrast_scope! end def cs__enter_assess_scope # If we shouldn't be doing assess things, don't propagate or whatever disable_contrast = skip_assess_analysis? return nil if disable_contrast enter_contrast_scope! end def cs__enter_scope_contrast_patch # If we're already in Contrast scope, don't propagate or whatever disable_contrast = skip_contrast_analysis? return nil if disable_contrast enter_contrast_scope! end end end end