contrast-agent 4.9.1 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.rspec +0 -1
 - data/.rspec_parallel +6 -0
 - data/ext/cs__contrast_patch/cs__contrast_patch.c +0 -1
 - data/ext/cs__contrast_patch/cs__contrast_patch.h +0 -2
 - data/lib/contrast/agent/assess/contrast_event.rb +0 -1
 - data/lib/contrast/agent/assess/finalizers/hash.rb +0 -1
 - data/lib/contrast/agent/assess/policy/patcher.rb +0 -1
 - data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -2
 - data/lib/contrast/agent/assess/policy/preshift.rb +8 -5
 - data/lib/contrast/agent/assess/policy/propagation_method.rb +100 -57
 - data/lib/contrast/agent/assess/policy/propagator/database_write.rb +0 -2
 - data/lib/contrast/agent/assess/policy/propagator/match_data.rb +31 -11
 - data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -2
 - data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -0
 - data/lib/contrast/agent/assess/policy/rewriter_patch.rb +0 -1
 - data/lib/contrast/agent/assess/policy/source_method.rb +13 -17
 - data/lib/contrast/agent/assess/policy/trigger/xpath.rb +0 -1
 - data/lib/contrast/agent/assess/policy/trigger_method.rb +59 -83
 - data/lib/contrast/agent/assess/property/evented.rb +2 -1
 - data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +0 -1
 - data/lib/contrast/agent/disable_reaction.rb +1 -1
 - data/lib/contrast/agent/exclusion_matcher.rb +0 -4
 - data/lib/contrast/agent/inventory/database_config.rb +117 -0
 - data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +5 -4
 - data/lib/contrast/agent/inventory/policy/datastores.rb +2 -2
 - data/lib/contrast/agent/middleware.rb +1 -0
 - data/lib/contrast/agent/patching/policy/after_load_patch.rb +3 -0
 - data/lib/contrast/agent/patching/policy/after_load_patcher.rb +18 -12
 - data/lib/contrast/agent/patching/policy/module_policy.rb +2 -4
 - data/lib/contrast/agent/patching/policy/patch.rb +5 -0
 - data/lib/contrast/agent/patching/policy/patch_status.rb +3 -7
 - data/lib/contrast/agent/patching/policy/patcher.rb +8 -8
 - data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
 - data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -53
 - data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +137 -0
 - data/lib/contrast/agent/protect/rule/sqli.rb +7 -70
 - data/lib/contrast/agent/reaction_processor.rb +1 -1
 - data/lib/contrast/agent/request.rb +5 -2
 - data/lib/contrast/agent/request_context.rb +19 -22
 - data/lib/contrast/agent/static_analysis.rb +1 -1
 - data/lib/contrast/agent/tracepoint_hook.rb +6 -1
 - data/lib/contrast/agent/version.rb +1 -1
 - data/lib/contrast/api/communication/messaging_queue.rb +12 -6
 - data/lib/contrast/api/communication/service_lifecycle.rb +4 -1
 - data/lib/contrast/api/communication/socket_client.rb +4 -4
 - data/lib/contrast/api/decorators/agent_startup.rb +4 -4
 - data/lib/contrast/api/decorators/application_startup.rb +6 -5
 - data/lib/contrast/api/decorators/route_coverage.rb +24 -1
 - data/lib/contrast/components/agent.rb +5 -2
 - data/lib/contrast/components/assess.rb +6 -3
 - data/lib/contrast/components/base.rb +2 -2
 - data/lib/contrast/components/config.rb +1 -0
 - data/lib/contrast/components/contrast_service.rb +4 -2
 - data/lib/contrast/components/logger.rb +13 -8
 - data/lib/contrast/components/scope.rb +9 -28
 - data/lib/contrast/config/base_configuration.rb +14 -6
 - data/lib/contrast/configuration.rb +19 -15
 - data/lib/contrast/extension/assess/array.rb +1 -11
 - data/lib/contrast/extension/assess/eval_trigger.rb +0 -20
 - data/lib/contrast/extension/assess/fiber.rb +0 -11
 - data/lib/contrast/extension/assess/hash.rb +0 -10
 - data/lib/contrast/extension/assess/kernel.rb +1 -10
 - data/lib/contrast/extension/assess/marshal.rb +3 -11
 - data/lib/contrast/extension/assess/regexp.rb +0 -11
 - data/lib/contrast/extension/assess/string.rb +1 -26
 - data/lib/contrast/extension/extension.rb +61 -0
 - data/lib/contrast/extension/protect/kernel.rb +0 -10
 - data/lib/contrast/framework/grape/support.rb +174 -0
 - data/lib/contrast/framework/manager.rb +42 -6
 - data/lib/contrast/framework/rack/support.rb +1 -1
 - data/lib/contrast/framework/rails/patch/assess_configuration.rb +0 -1
 - data/lib/contrast/framework/rails/patch/support.rb +6 -3
 - data/lib/contrast/framework/rails/railtie.rb +1 -1
 - data/lib/contrast/framework/rails/rewrite/active_record_named.rb +1 -0
 - data/lib/contrast/framework/rails/support.rb +60 -13
 - data/lib/contrast/framework/sinatra/support.rb +1 -1
 - data/lib/contrast/logger/log.rb +89 -15
 - data/lib/contrast/utils/io_util.rb +1 -1
 - data/lib/contrast/utils/ruby_ast_rewriter.rb +16 -13
 - data/lib/contrast/utils/tag_util.rb +2 -1
 - data/resources/assess/policy.json +197 -2
 - data/resources/deadzone/policy.json +10 -0
 - data/ruby-agent.gemspec +10 -1
 - metadata +78 -12
 - data/lib/contrast/utils/inventory_util.rb +0 -113
 
| 
         @@ -106,7 +106,7 @@ module Contrast 
     | 
|
| 
       106 
106 
     | 
    
         
             
                      def _route_recurse controller, method, route
         
     | 
| 
       107 
107 
     | 
    
         
             
                        return if controller.nil? || controller.cs__class == NilClass
         
     | 
| 
       108 
108 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                        route_patterns = controller.routes.fetch(method 
     | 
| 
      
 109 
     | 
    
         
            +
                        route_patterns = controller.routes.fetch(method) { [] }.map(&:first)
         
     | 
| 
       110 
110 
     | 
    
         
             
                        route_pattern = route_patterns&.find do |matcher|
         
     | 
| 
       111 
111 
     | 
    
         
             
                          matcher.params(route) # ::Mustermann::Sinatra match.
         
     | 
| 
       112 
112 
     | 
    
         
             
                        end
         
     | 
    
        data/lib/contrast/logger/log.rb
    CHANGED
    
    | 
         @@ -13,6 +13,75 @@ require 'contrast/logger/time' 
     | 
|
| 
       13 
13 
     | 
    
         
             
            require 'contrast/components/config'
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
            module Contrast
         
     | 
| 
      
 16 
     | 
    
         
            +
              # This module allows us to dynamically weave timing into our code, so that only when the time is actually needed do
         
     | 
| 
      
 17 
     | 
    
         
            +
              # we pay the penalty for that timing block
         
     | 
| 
      
 18 
     | 
    
         
            +
              module TraceTiming
         
     | 
| 
      
 19 
     | 
    
         
            +
                def methods_to_time
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @_methods_to_time ||= []
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Store info about methods for later patching.
         
     | 
| 
      
 24 
     | 
    
         
            +
                METHOD_INFO = Struct.new(:clazz, :method_name, :custom_msg, :aliased)
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                # Add a method to the list of methods to be trace timed if logger set to TRACE. Enables trace timing after if
         
     | 
| 
      
 27 
     | 
    
         
            +
                # logger set to TRACE.
         
     | 
| 
      
 28 
     | 
    
         
            +
                #
         
     | 
| 
      
 29 
     | 
    
         
            +
                # @params: clazz [Class] the class of the method to time.
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @params: method [Symbol] the method to time.
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @params: method [String] optional custom logging message.
         
     | 
| 
      
 32 
     | 
    
         
            +
                def add_method_to_trace_timing clazz, method, msg = nil
         
     | 
| 
      
 33 
     | 
    
         
            +
                  methods_to_time.append(METHOD_INFO.new(clazz, method, msg, false))
         
     | 
| 
      
 34 
     | 
    
         
            +
                  enable_trace_timing if logger.level == ::Ougai::Logging::TRACE
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # Add a method to the list of methods to be trace timed if logger set to TRACE. Enables trace timing after if
         
     | 
| 
      
 38 
     | 
    
         
            +
                # logger set to TRACE.
         
     | 
| 
      
 39 
     | 
    
         
            +
                #
         
     | 
| 
      
 40 
     | 
    
         
            +
                # @params: method_spec [METHOD_INFO] specs about the method to be timed.
         
     | 
| 
      
 41 
     | 
    
         
            +
                # @params: class_method [Boolean] whether this is or isn't a class/module method.
         
     | 
| 
      
 42 
     | 
    
         
            +
                def trace_time_class_method meth_spec, class_method
         
     | 
| 
      
 43 
     | 
    
         
            +
                  untimed_func_symbol = "untimed_#{ meth_spec.method_name }".to_sym
         
     | 
| 
      
 44 
     | 
    
         
            +
                  send_to = class_method ? meth_spec.clazz.cs__singleton_class : meth_spec.clazz
         
     | 
| 
      
 45 
     | 
    
         
            +
                  meth_spec.clazz.class_eval do
         
     | 
| 
      
 46 
     | 
    
         
            +
                    include Contrast::Components::Logger::InstanceMethods
         
     | 
| 
      
 47 
     | 
    
         
            +
                    extend Contrast::Components::Logger::InstanceMethods
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    send_to.send(:alias_method, untimed_func_symbol, meth_spec.method_name)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    meth_spec.aliased = true
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    log_message = "Elapsed time for #{ meth_spec.method_name }."
         
     | 
| 
      
 53 
     | 
    
         
            +
                    log_message = meth_spec.custom_message if meth_spec.custom_msg
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    send_to.send(:define_method, meth_spec.method_name) do |*args, **kwargs, &block| # rubocop:disable Performance/Kernel/DefineMethod
         
     | 
| 
      
 56 
     | 
    
         
            +
                      start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         
     | 
| 
      
 57 
     | 
    
         
            +
                      rv = if kwargs.empty?
         
     | 
| 
      
 58 
     | 
    
         
            +
                             send(untimed_func_symbol, *args, &block)
         
     | 
| 
      
 59 
     | 
    
         
            +
                           else
         
     | 
| 
      
 60 
     | 
    
         
            +
                             send(untimed_func_symbol, *args, **kwargs, &block)
         
     | 
| 
      
 61 
     | 
    
         
            +
                           end
         
     | 
| 
      
 62 
     | 
    
         
            +
                      delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
         
     | 
| 
      
 63 
     | 
    
         
            +
                      logger.trace(log_message, elapsed: delta * 1000)
         
     | 
| 
      
 64 
     | 
    
         
            +
                      rv
         
     | 
| 
      
 65 
     | 
    
         
            +
                    end
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                # Enable trace timing of methods specified in @_methods_to_time via aliasing.
         
     | 
| 
      
 70 
     | 
    
         
            +
                def enable_trace_timing
         
     | 
| 
      
 71 
     | 
    
         
            +
                  methods_to_time.each do |meth_spec|
         
     | 
| 
      
 72 
     | 
    
         
            +
                    next if meth_spec.aliased
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    is_class_method = meth_spec.clazz.singleton_methods(false).include?(meth_spec.method_name)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    trace_time_class_method meth_spec, is_class_method
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            module Contrast
         
     | 
| 
      
 82 
     | 
    
         
            +
              # Used as a wrapper around our logging. The module option specifically adds in a new method for error that raises the
         
     | 
| 
      
 83 
     | 
    
         
            +
              # logged exception, used in testing so that we can see if anything unexpected happens without it being swallowed
         
     | 
| 
      
 84 
     | 
    
         
            +
              # while still providing safe options for customers.
         
     | 
| 
       16 
85 
     | 
    
         
             
              module Logger
         
     | 
| 
       17 
86 
     | 
    
         
             
                # For development set following env var to raise logged exceptions instead of just logging.
         
     | 
| 
       18 
87 
     | 
    
         
             
                if ENV['CONTRAST__AGENT__RUBY_MORE_COWBELL']
         
     | 
| 
         @@ -20,22 +89,22 @@ module Contrast 
     | 
|
| 
       20 
89 
     | 
    
         
             
                    alias_method :cs__error, :error
         
     | 
| 
       21 
90 
     | 
    
         
             
                    alias_method :cs__warn, :warn
         
     | 
| 
       22 
91 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                    def error  
     | 
| 
       24 
     | 
    
         
            -
                       
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                       
     | 
| 
       30 
     | 
    
         
            -
                      raise exc if exc && exc.cs__class < Exception
         
     | 
| 
      
 92 
     | 
    
         
            +
                    def error *args, **kwargs
         
     | 
| 
      
 93 
     | 
    
         
            +
                      if kwargs.empty?
         
     | 
| 
      
 94 
     | 
    
         
            +
                        cs__error(*args)
         
     | 
| 
      
 95 
     | 
    
         
            +
                      else
         
     | 
| 
      
 96 
     | 
    
         
            +
                        cs__error(*args, **kwargs)
         
     | 
| 
      
 97 
     | 
    
         
            +
                      end
         
     | 
| 
      
 98 
     | 
    
         
            +
                      args.each { |arg| raise arg if arg && arg.cs__class < Exception }
         
     | 
| 
       31 
99 
     | 
    
         
             
                    end
         
     | 
| 
       32 
100 
     | 
    
         
             
                  end
         
     | 
| 
       33 
101 
     | 
    
         
             
                end
         
     | 
| 
       34 
102 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                # This class functions to serve as a wrapper around our logging, as we need
         
     | 
| 
       36 
     | 
    
         
            -
                #  
     | 
| 
      
 103 
     | 
    
         
            +
                # This class functions to serve as a wrapper around our logging, as we need to be able to dynamically update
         
     | 
| 
      
 104 
     | 
    
         
            +
                # level based on updates to TeamServer.
         
     | 
| 
       37 
105 
     | 
    
         
             
                class Log
         
     | 
| 
       38 
106 
     | 
    
         
             
                  include Singleton
         
     | 
| 
      
 107 
     | 
    
         
            +
                  include ::Contrast::TraceTiming
         
     | 
| 
       39 
108 
     | 
    
         | 
| 
       40 
109 
     | 
    
         
             
                  DEFAULT_NAME     = 'contrast.log'
         
     | 
| 
       41 
110 
     | 
    
         
             
                  DEFAULT_LEVEL    = ::Ougai::Logging::Severity::INFO
         
     | 
| 
         @@ -49,8 +118,8 @@ module Contrast 
     | 
|
| 
       49 
118 
     | 
    
         
             
                    update
         
     | 
| 
       50 
119 
     | 
    
         
             
                  end
         
     | 
| 
       51 
120 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                  # Given new settings from TeamServer, update our logging to use the new
         
     | 
| 
       53 
     | 
    
         
            -
                  #  
     | 
| 
      
 121 
     | 
    
         
            +
                  # Given new settings from TeamServer, update our logging to use the new file and level, assuming they weren't
         
     | 
| 
      
 122 
     | 
    
         
            +
                  # set by local configuration.
         
     | 
| 
       54 
123 
     | 
    
         
             
                  #
         
     | 
| 
       55 
124 
     | 
    
         
             
                  # @param log_file [String] the file to which to log, as provided by TeamServer settings
         
     | 
| 
       56 
125 
     | 
    
         
             
                  # @param log_level [String] the level at which to log, as provided by TeamServer settings
         
     | 
| 
         @@ -67,6 +136,8 @@ module Contrast 
     | 
|
| 
       67 
136 
     | 
    
         
             
                    @previous_path  = current_path
         
     | 
| 
       68 
137 
     | 
    
         
             
                    @previous_level = current_level_const
         
     | 
| 
       69 
138 
     | 
    
         | 
| 
      
 139 
     | 
    
         
            +
                    enable_trace_timing if current_level_const == ::Ougai::Logging::TRACE
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
       70 
141 
     | 
    
         
             
                    @_logger = build(path: current_path, level_const: current_level_const)
         
     | 
| 
       71 
142 
     | 
    
         
             
                    # If we're logging to a new path, then let's start it w/ our helpful
         
     | 
| 
       72 
143 
     | 
    
         
             
                    # data gathering messages
         
     | 
| 
         @@ -76,6 +147,9 @@ module Contrast 
     | 
|
| 
       76 
147 
     | 
    
         
             
                      logger.error('Unable to process update to LoggerManager.', e)
         
     | 
| 
       77 
148 
     | 
    
         
             
                    else
         
     | 
| 
       78 
149 
     | 
    
         
             
                      puts 'Unable to process update to LoggerManager.'
         
     | 
| 
      
 150 
     | 
    
         
            +
                      raise e if ENV['CONTRAST__AGENT__RUBY_MORE_COWBELL']
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                      puts e.message
         
     | 
| 
       79 
153 
     | 
    
         
             
                      puts e.backtrace.join("\n")
         
     | 
| 
       80 
154 
     | 
    
         
             
                    end
         
     | 
| 
       81 
155 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -158,7 +232,8 @@ module Contrast 
     | 
|
| 
       158 
232 
     | 
    
         
             
                  # @return [::Ougai::Logging::Severity] the level at which to log
         
     | 
| 
       159 
233 
     | 
    
         
             
                  def find_valid_level log_level
         
     | 
| 
       160 
234 
     | 
    
         
             
                    config = ::Contrast::CONFIG.root.agent.logger
         
     | 
| 
       161 
     | 
    
         
            -
                    config_level = config 
     | 
| 
      
 235 
     | 
    
         
            +
                    config_level = config&.level&.length&.positive? ? config.level : nil
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
       162 
237 
     | 
    
         
             
                    valid_level(config_level || log_level)
         
     | 
| 
       163 
238 
     | 
    
         
             
                  end
         
     | 
| 
       164 
239 
     | 
    
         | 
| 
         @@ -174,8 +249,7 @@ module Contrast 
     | 
|
| 
       174 
249 
     | 
    
         
             
                    DEFAULT_LEVEL
         
     | 
| 
       175 
250 
     | 
    
         
             
                  end
         
     | 
| 
       176 
251 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
                  # Log that the Agent log has changed and include some default information
         
     | 
| 
       178 
     | 
    
         
            -
                  # at the start of the log.
         
     | 
| 
      
 252 
     | 
    
         
            +
                  # Log that the Agent log has changed and include some default information at the start of the log.
         
     | 
| 
       179 
253 
     | 
    
         
             
                  def log_update
         
     | 
| 
       180 
254 
     | 
    
         
             
                    logger.debug('Initialized new contrast agent logger')
         
     | 
| 
       181 
255 
     | 
    
         
             
                    logger.debug_with_time('middleware: log environment') do
         
     | 
| 
         @@ -6,7 +6,7 @@ require 'contrast/components/logger' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            module Contrast
         
     | 
| 
       7 
7 
     | 
    
         
             
              module Utils
         
     | 
| 
       8 
8 
     | 
    
         
             
                # Util for information about an IO
         
     | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
      
 9 
     | 
    
         
            +
                module IOUtil
         
     | 
| 
       10 
10 
     | 
    
         
             
                  extend Contrast::Components::Logger::InstanceMethods
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                  # We're only going to call rewind on things that we believe are safe to
         
     | 
| 
         @@ -36,36 +36,39 @@ module Contrast 
     | 
|
| 
       36 
36 
     | 
    
         
             
                  # the replace within the given node.
         
     | 
| 
       37 
37 
     | 
    
         
             
                  def on_dstr node
         
     | 
| 
       38 
38 
     | 
    
         
             
                    return if node.children.all? { |child_node| child_node.type == :str }
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
39 
     | 
    
         
             
                    new_content = +'('
         
     | 
| 
       41 
     | 
    
         
            -
                     
     | 
| 
      
 40 
     | 
    
         
            +
                    idx = 0
         
     | 
| 
      
 41 
     | 
    
         
            +
                    while idx < node.children.size
         
     | 
| 
      
 42 
     | 
    
         
            +
                      #node.children.each_with_index do |child_node, index|
         
     | 
| 
      
 43 
     | 
    
         
            +
                      child_node = node.children[idx]
         
     | 
| 
       42 
44 
     | 
    
         
             
                      # A begin node looks like #{some_code} in ruby, we do a substring
         
     | 
| 
       43 
45 
     | 
    
         
             
                      # from [2...-1] to get rid of the #{ & trailing }.
         
     | 
| 
       44 
46 
     | 
    
         
             
                      if child_node.type == :begin
         
     | 
| 
       45 
47 
     | 
    
         
             
                        code = child_node.
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 48 
     | 
    
         
            +
                          location.
         
     | 
| 
      
 49 
     | 
    
         
            +
                          expression.
         
     | 
| 
      
 50 
     | 
    
         
            +
                          source_buffer.
         
     | 
| 
      
 51 
     | 
    
         
            +
                          source[child_node.location.begin.begin_pos...child_node.location.end.end_pos]
         
     | 
| 
       50 
52 
     | 
    
         
             
                        code = code[2...-1]
         
     | 
| 
       51 
53 
     | 
    
         
             
                        new_content += "((#{ code }).to_s)"
         
     | 
| 
       52 
54 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
      
 55 
     | 
    
         
            +
                        # For interpolations that use class, instance, or global variables,
         
     | 
| 
      
 56 
     | 
    
         
            +
                        # those are NOT within a begin block, but instead are a ivar, cvar,
         
     | 
| 
      
 57 
     | 
    
         
            +
                        # or gvar node, not stripping of interpolation markers required.
         
     | 
| 
       56 
58 
     | 
    
         
             
                      elsif VARIABLES.include?(child_node.type)
         
     | 
| 
       57 
59 
     | 
    
         
             
                        variable = child_node.children.first
         
     | 
| 
       58 
60 
     | 
    
         
             
                        new_content << "((#{ variable }).to_s)"
         
     | 
| 
       59 
61 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
      
 62 
     | 
    
         
            +
                        # When interpolation includes strings before or after an
         
     | 
| 
      
 63 
     | 
    
         
            +
                        # interpolation they are simple :str nodes, in order to preserve
         
     | 
| 
      
 64 
     | 
    
         
            +
                        # escaping we need to do a dump of the string value.
         
     | 
| 
       63 
65 
     | 
    
         
             
                      elsif child_node.type == :str
         
     | 
| 
       64 
66 
     | 
    
         
             
                        literal_value = child_node.children.first
         
     | 
| 
       65 
67 
     | 
    
         
             
                        literal_value = literal_value.dump[1...-1]
         
     | 
| 
       66 
68 
     | 
    
         
             
                        new_content <<  "\"#{ literal_value }\""
         
     | 
| 
       67 
69 
     | 
    
         
             
                      end
         
     | 
| 
       68 
     | 
    
         
            -
                      new_content << ' + ' unless  
     | 
| 
      
 70 
     | 
    
         
            +
                      new_content << ' + ' unless idx == node.children.length - 1
         
     | 
| 
      
 71 
     | 
    
         
            +
                      idx += 1
         
     | 
| 
       69 
72 
     | 
    
         
             
                    end
         
     | 
| 
       70 
73 
     | 
    
         
             
                    new_content << ')'
         
     | 
| 
       71 
74 
     | 
    
         
             
                    if node.location.cs__respond_to?(:heredoc_body)
         
     | 
| 
         @@ -8,7 +8,8 @@ module Contrast 
     | 
|
| 
       8 
8 
     | 
    
         
             
                  class << self
         
     | 
| 
       9 
9 
     | 
    
         
             
                    # Determine if the given array of tags is covered by the other
         
     | 
| 
       10 
10 
     | 
    
         
             
                    #
         
     | 
| 
       11 
     | 
    
         
            -
                    # @param remaining_ranges [Array<Contrast::Agent::Assess::Tag>] the tags left that haven't been covered by 
     | 
| 
      
 11 
     | 
    
         
            +
                    # @param remaining_ranges [Array<Contrast::Agent::Assess::Tag>] the tags left that haven't been covered by
         
     | 
| 
      
 12 
     | 
    
         
            +
                    #   those given
         
     | 
| 
       12 
13 
     | 
    
         
             
                    # @param ranges Array<Contrast::Agent::Assess::Tag> the tags that are covering the first
         
     | 
| 
       13 
14 
     | 
    
         
             
                    def covered? remaining_ranges, ranges
         
     | 
| 
       14 
15 
     | 
    
         
             
                      return true unless remaining_ranges&.any?
         
     | 
| 
         @@ -34,6 +34,23 @@ 
     | 
|
| 
       34 
34 
     | 
    
         
             
                  "type": "BODY",
         
     | 
| 
       35 
35 
     | 
    
         
             
                  "tags":["NO_NEWLINES", "CROSS_SITE"]
         
     | 
| 
       36 
36 
     | 
    
         
             
                }, {
         
     | 
| 
      
 37 
     | 
    
         
            +
                  "class_name":"ActionDispatch::Request",
         
     | 
| 
      
 38 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 39 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 40 
     | 
    
         
            +
                  "method_name": "body",
         
     | 
| 
      
 41 
     | 
    
         
            +
                  "source": "P0",
         
     | 
| 
      
 42 
     | 
    
         
            +
                  "target": "R",
         
     | 
| 
      
 43 
     | 
    
         
            +
                  "type": "BODY",
         
     | 
| 
      
 44 
     | 
    
         
            +
                  "tags":["NO_NEWLINES", "CROSS_SITE"]
         
     | 
| 
      
 45 
     | 
    
         
            +
                },  {
         
     | 
| 
      
 46 
     | 
    
         
            +
                  "class_name":"ActionDispatch::Cookies::CookieJar",
         
     | 
| 
      
 47 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 48 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 49 
     | 
    
         
            +
                  "method_name": "[]",
         
     | 
| 
      
 50 
     | 
    
         
            +
                  "target": "R",
         
     | 
| 
      
 51 
     | 
    
         
            +
                  "type": "COOKIE",
         
     | 
| 
      
 52 
     | 
    
         
            +
                  "tags":["NO_NEWLINES", "CROSS_SITE"]
         
     | 
| 
      
 53 
     | 
    
         
            +
                },  {
         
     | 
| 
       37 
54 
     | 
    
         
             
                  "class_name":"Rack::Request::Helpers",
         
     | 
| 
       38 
55 
     | 
    
         
             
                  "instance_method": true,
         
     | 
| 
       39 
56 
     | 
    
         
             
                  "method_visibility": "public",
         
     | 
| 
         @@ -129,10 +146,45 @@ 
     | 
|
| 
       129 
146 
     | 
    
         
             
                  "target":"R",
         
     | 
| 
       130 
147 
     | 
    
         
             
                  "type":"PARAMETER",
         
     | 
| 
       131 
148 
     | 
    
         
             
                  "tags":["CROSS_SITE"]
         
     | 
| 
      
 149 
     | 
    
         
            +
                }, {
         
     | 
| 
      
 150 
     | 
    
         
            +
                  "class_name":"Grape::Env",
         
     | 
| 
      
 151 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 152 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 153 
     | 
    
         
            +
                  "method_name":"[]",
         
     | 
| 
      
 154 
     | 
    
         
            +
                  "source": "P0",
         
     | 
| 
      
 155 
     | 
    
         
            +
                  "target":"R",
         
     | 
| 
      
 156 
     | 
    
         
            +
                  "type":"HEADER",
         
     | 
| 
      
 157 
     | 
    
         
            +
                  "tags":["CROSS_SITE"]
         
     | 
| 
      
 158 
     | 
    
         
            +
                }, {
         
     | 
| 
      
 159 
     | 
    
         
            +
                  "class_name":"Grape::Request",
         
     | 
| 
      
 160 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 161 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 162 
     | 
    
         
            +
                  "method_name":"headers",
         
     | 
| 
      
 163 
     | 
    
         
            +
                  "source": "P0",
         
     | 
| 
      
 164 
     | 
    
         
            +
                  "target":"R",
         
     | 
| 
      
 165 
     | 
    
         
            +
                  "type":"HEADER",
         
     | 
| 
      
 166 
     | 
    
         
            +
                  "tags":["NO_NEWLINES", "CROSS_SITE"]
         
     | 
| 
      
 167 
     | 
    
         
            +
                }, {
         
     | 
| 
      
 168 
     | 
    
         
            +
                  "class_name":"Grape::Request",
         
     | 
| 
      
 169 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 170 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 171 
     | 
    
         
            +
                  "method_name":"body",
         
     | 
| 
      
 172 
     | 
    
         
            +
                  "target":"R",
         
     | 
| 
      
 173 
     | 
    
         
            +
                  "type":"BODY",
         
     | 
| 
      
 174 
     | 
    
         
            +
                  "tags":["CROSS_SITE"]
         
     | 
| 
      
 175 
     | 
    
         
            +
                }, {
         
     | 
| 
      
 176 
     | 
    
         
            +
                  "class_name":"Grape::Validations::Base",
         
     | 
| 
      
 177 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 178 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 179 
     | 
    
         
            +
                  "method_name":"validate!",
         
     | 
| 
      
 180 
     | 
    
         
            +
                  "source": "P0",
         
     | 
| 
      
 181 
     | 
    
         
            +
                  "target":"R",
         
     | 
| 
      
 182 
     | 
    
         
            +
                  "type":"PARAMETER",
         
     | 
| 
      
 183 
     | 
    
         
            +
                  "tags":["CROSS_SITE"]
         
     | 
| 
       132 
184 
     | 
    
         
             
                }
         
     | 
| 
       133 
185 
     | 
    
         
             
              ],
         
     | 
| 
       134 
186 
     | 
    
         
             
              "propagators":[
         
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
      
 187 
     | 
    
         
            +
                 {
         
     | 
| 
       136 
188 
     | 
    
         
             
                  "class_name":"String",
         
     | 
| 
       137 
189 
     | 
    
         
             
                  "instance_method": true,
         
     | 
| 
       138 
190 
     | 
    
         
             
                  "method_visibility": "public",
         
     | 
| 
         @@ -140,7 +192,7 @@ 
     | 
|
| 
       140 
192 
     | 
    
         
             
                  "source":"O",
         
     | 
| 
       141 
193 
     | 
    
         
             
                  "target":"R",
         
     | 
| 
       142 
194 
     | 
    
         
             
                  "action":"KEEP"
         
     | 
| 
       143 
     | 
    
         
            -
                }, 
     | 
| 
      
 195 
     | 
    
         
            +
                }, {
         
     | 
| 
       144 
196 
     | 
    
         
             
                  "class_name": "String",
         
     | 
| 
       145 
197 
     | 
    
         
             
                  "instance_method": true,
         
     | 
| 
       146 
198 
     | 
    
         
             
                  "method_visibility": "public",
         
     | 
| 
         @@ -722,6 +774,24 @@ 
     | 
|
| 
       722 
774 
     | 
    
         
             
                  "patch_method": "select_tagger",
         
     | 
| 
       723 
775 
     | 
    
         
             
                  "source": "O",
         
     | 
| 
       724 
776 
     | 
    
         
             
                  "target": "R"
         
     | 
| 
      
 777 
     | 
    
         
            +
                },{
         
     | 
| 
      
 778 
     | 
    
         
            +
                  "class_name":"CGI::Util",
         
     | 
| 
      
 779 
     | 
    
         
            +
                  "method_name":"unescape",
         
     | 
| 
      
 780 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 781 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 782 
     | 
    
         
            +
                  "source":"P0",
         
     | 
| 
      
 783 
     | 
    
         
            +
                  "target":"R",
         
     | 
| 
      
 784 
     | 
    
         
            +
                  "action":"SPLAT",
         
     | 
| 
      
 785 
     | 
    
         
            +
                  "tags":[],
         
     | 
| 
      
 786 
     | 
    
         
            +
                  "untags":[]
         
     | 
| 
      
 787 
     | 
    
         
            +
                }, {
         
     | 
| 
      
 788 
     | 
    
         
            +
                  "class_name":"StringIO",
         
     | 
| 
      
 789 
     | 
    
         
            +
                  "instance_method": true,
         
     | 
| 
      
 790 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 791 
     | 
    
         
            +
                  "method_name": "read",
         
     | 
| 
      
 792 
     | 
    
         
            +
                  "source": "O",
         
     | 
| 
      
 793 
     | 
    
         
            +
                  "target": "R",
         
     | 
| 
      
 794 
     | 
    
         
            +
                  "action": "SPLAT"
         
     | 
| 
       725 
795 
     | 
    
         
             
                }, {
         
     | 
| 
       726 
796 
     | 
    
         
             
                  "class_name":"CGI::Util",
         
     | 
| 
       727 
797 
     | 
    
         
             
                  "method_name":"escapeHTML",
         
     | 
| 
         @@ -742,6 +812,16 @@ 
     | 
|
| 
       742 
812 
     | 
    
         
             
                  "action":"SPLAT",
         
     | 
| 
       743 
813 
     | 
    
         
             
                  "tags":["HTML_ENCODED"],
         
     | 
| 
       744 
814 
     | 
    
         
             
                  "untags":["HTML_DECODED"]
         
     | 
| 
      
 815 
     | 
    
         
            +
                }, {
         
     | 
| 
      
 816 
     | 
    
         
            +
                  "class_name":"Rack::Utils",
         
     | 
| 
      
 817 
     | 
    
         
            +
                  "method_name":"escape_html",
         
     | 
| 
      
 818 
     | 
    
         
            +
                  "instance_method": false,
         
     | 
| 
      
 819 
     | 
    
         
            +
                  "method_visibility": "public",
         
     | 
| 
      
 820 
     | 
    
         
            +
                  "source":"P0",
         
     | 
| 
      
 821 
     | 
    
         
            +
                  "target":"R",
         
     | 
| 
      
 822 
     | 
    
         
            +
                  "action":"SPLAT",
         
     | 
| 
      
 823 
     | 
    
         
            +
                  "tags":["HTML_ENCODED"],
         
     | 
| 
      
 824 
     | 
    
         
            +
                  "untags":["HTML_DECODED"]
         
     | 
| 
       745 
825 
     | 
    
         
             
                }, {
         
     | 
| 
       746 
826 
     | 
    
         
             
                  "class_name":"CGI::Util",
         
     | 
| 
       747 
827 
     | 
    
         
             
                  "method_name":"h",
         
     | 
| 
         @@ -1287,6 +1367,18 @@ 
     | 
|
| 
       1287 
1367 
     | 
    
         
             
                      "instance_method": true,
         
     | 
| 
       1288 
1368 
     | 
    
         
             
                      "method_visibility": "public",
         
     | 
| 
       1289 
1369 
     | 
    
         
             
                      "source":"P0"
         
     | 
| 
      
 1370 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1371 
     | 
    
         
            +
                      "class_name":"Rack::Response",
         
     | 
| 
      
 1372 
     | 
    
         
            +
                      "method_name":"body=",
         
     | 
| 
      
 1373 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1374 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1375 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1376 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1377 
     | 
    
         
            +
                      "class_name":"Rack::Response",
         
     | 
| 
      
 1378 
     | 
    
         
            +
                      "method_name":"write",
         
     | 
| 
      
 1379 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1380 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1381 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
       1290 
1382 
     | 
    
         
             
                    }, {
         
     | 
| 
       1291 
1383 
     | 
    
         
             
                      "class_name":"Sinatra::Helpers",
         
     | 
| 
       1292 
1384 
     | 
    
         
             
                      "method_name":"body",
         
     | 
| 
         @@ -1347,12 +1439,108 @@ 
     | 
|
| 
       1347 
1439 
     | 
    
         
             
                      "method_visibility": "public",
         
     | 
| 
       1348 
1440 
     | 
    
         
             
                      "method_name":"async_exec",
         
     | 
| 
       1349 
1441 
     | 
    
         
             
                      "source":"P0"
         
     | 
| 
      
 1442 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1443 
     | 
    
         
            +
                      "class_name":"ActiveRecord::Relation::Calculations",
         
     | 
| 
      
 1444 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1445 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1446 
     | 
    
         
            +
                      "method_name":"calculate",
         
     | 
| 
      
 1447 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1448 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1449 
     | 
    
         
            +
                      "class_name":"ActiveRecord::FinderMethods",
         
     | 
| 
      
 1450 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1451 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1452 
     | 
    
         
            +
                      "method_name":"exists?",
         
     | 
| 
      
 1453 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1454 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1455 
     | 
    
         
            +
                      "class_name":"ActiveRecord::FinderMethods",
         
     | 
| 
      
 1456 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1457 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1458 
     | 
    
         
            +
                      "method_name":"find_by",
         
     | 
| 
      
 1459 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
       1350 
1460 
     | 
    
         
             
                    }, {
         
     | 
| 
       1351 
1461 
     | 
    
         
             
                      "class_name":"ActiveRecord::Querying",
         
     | 
| 
       1352 
1462 
     | 
    
         
             
                      "instance_method": false,
         
     | 
| 
       1353 
1463 
     | 
    
         
             
                      "method_visibility": "public",
         
     | 
| 
       1354 
1464 
     | 
    
         
             
                      "method_name":"select",
         
     | 
| 
       1355 
1465 
     | 
    
         
             
                      "source":"P0"
         
     | 
| 
      
 1466 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1467 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1468 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1469 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1470 
     | 
    
         
            +
                      "method_name":"from",
         
     | 
| 
      
 1471 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1472 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1473 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1474 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1475 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1476 
     | 
    
         
            +
                      "method_name":"group",
         
     | 
| 
      
 1477 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1478 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1479 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1480 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1481 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1482 
     | 
    
         
            +
                      "method_name":"having",
         
     | 
| 
      
 1483 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1484 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1485 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1486 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1487 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1488 
     | 
    
         
            +
                      "method_name":"joins",
         
     | 
| 
      
 1489 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1490 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1491 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1492 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1493 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1494 
     | 
    
         
            +
                      "method_name":"lock",
         
     | 
| 
      
 1495 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1496 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1497 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1498 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1499 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1500 
     | 
    
         
            +
                      "method_name":"select",
         
     | 
| 
      
 1501 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1502 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1503 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1504 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1505 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1506 
     | 
    
         
            +
                      "method_name":"reselect",
         
     | 
| 
      
 1507 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1508 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1509 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1510 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1511 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1512 
     | 
    
         
            +
                      "method_name":"where",
         
     | 
| 
      
 1513 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1514 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1515 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods",
         
     | 
| 
      
 1516 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1517 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1518 
     | 
    
         
            +
                      "method_name":"rewhere",
         
     | 
| 
      
 1519 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1520 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1521 
     | 
    
         
            +
                      "class_name":"ActiveRecord::QueryMethods::WhereChain",
         
     | 
| 
      
 1522 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1523 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1524 
     | 
    
         
            +
                      "method_name":"not",
         
     | 
| 
      
 1525 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1526 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1527 
     | 
    
         
            +
                      "class_name":"ActiveRecord::Relation",
         
     | 
| 
      
 1528 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1529 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1530 
     | 
    
         
            +
                      "method_name":"delete_by",
         
     | 
| 
      
 1531 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1532 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1533 
     | 
    
         
            +
                      "class_name":"ActiveRecord::Relation",
         
     | 
| 
      
 1534 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1535 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1536 
     | 
    
         
            +
                      "method_name":"destroy_by",
         
     | 
| 
      
 1537 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
      
 1538 
     | 
    
         
            +
                    }, {
         
     | 
| 
      
 1539 
     | 
    
         
            +
                      "class_name":"ActiveRecord::Relation",
         
     | 
| 
      
 1540 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1541 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1542 
     | 
    
         
            +
                      "method_name":"update_all",
         
     | 
| 
      
 1543 
     | 
    
         
            +
                      "source":"P0"
         
     | 
| 
       1356 
1544 
     | 
    
         
             
                    }
         
     | 
| 
       1357 
1545 
     | 
    
         
             
                  ]
         
     | 
| 
       1358 
1546 
     | 
    
         
             
                }, {
         
     | 
| 
         @@ -1685,6 +1873,13 @@ 
     | 
|
| 
       1685 
1873 
     | 
    
         
             
                      "method_visibility": "public",
         
     | 
| 
       1686 
1874 
     | 
    
         
             
                      "method_name": "redirect_to",
         
     | 
| 
       1687 
1875 
     | 
    
         
             
                      "source": "P0"
         
     | 
| 
      
 1876 
     | 
    
         
            +
                    },
         
     | 
| 
      
 1877 
     | 
    
         
            +
                    {
         
     | 
| 
      
 1878 
     | 
    
         
            +
                      "class_name": "Grape::DSL::InsideRoute",
         
     | 
| 
      
 1879 
     | 
    
         
            +
                      "instance_method": true,
         
     | 
| 
      
 1880 
     | 
    
         
            +
                      "method_visibility": "public",
         
     | 
| 
      
 1881 
     | 
    
         
            +
                      "method_name": "redirect",
         
     | 
| 
      
 1882 
     | 
    
         
            +
                      "source": "P0"
         
     | 
| 
       1688 
1883 
     | 
    
         
             
                    }
         
     | 
| 
       1689 
1884 
     | 
    
         
             
                  ]
         
     | 
| 
       1690 
1885 
     | 
    
         
             
                }, {
         
     |