contrast-agent 4.9.1 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.rspec_parallel +6 -0
  4. data/ext/cs__contrast_patch/cs__contrast_patch.c +0 -1
  5. data/ext/cs__contrast_patch/cs__contrast_patch.h +0 -2
  6. data/lib/contrast/agent/assess/contrast_event.rb +0 -1
  7. data/lib/contrast/agent/assess/finalizers/hash.rb +0 -1
  8. data/lib/contrast/agent/assess/policy/patcher.rb +0 -1
  9. data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -2
  10. data/lib/contrast/agent/assess/policy/preshift.rb +8 -5
  11. data/lib/contrast/agent/assess/policy/propagation_method.rb +100 -57
  12. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +0 -2
  13. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +31 -11
  14. data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -2
  15. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -0
  16. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +0 -1
  17. data/lib/contrast/agent/assess/policy/source_method.rb +13 -17
  18. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +0 -1
  19. data/lib/contrast/agent/assess/policy/trigger_method.rb +59 -83
  20. data/lib/contrast/agent/assess/property/evented.rb +2 -1
  21. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +0 -1
  22. data/lib/contrast/agent/disable_reaction.rb +1 -1
  23. data/lib/contrast/agent/exclusion_matcher.rb +0 -4
  24. data/lib/contrast/agent/inventory/database_config.rb +117 -0
  25. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +5 -4
  26. data/lib/contrast/agent/inventory/policy/datastores.rb +2 -2
  27. data/lib/contrast/agent/middleware.rb +1 -0
  28. data/lib/contrast/agent/patching/policy/after_load_patch.rb +3 -0
  29. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +18 -12
  30. data/lib/contrast/agent/patching/policy/module_policy.rb +2 -4
  31. data/lib/contrast/agent/patching/policy/patch.rb +5 -0
  32. data/lib/contrast/agent/patching/policy/patch_status.rb +3 -7
  33. data/lib/contrast/agent/patching/policy/patcher.rb +8 -8
  34. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
  35. data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -53
  36. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +137 -0
  37. data/lib/contrast/agent/protect/rule/sqli.rb +7 -70
  38. data/lib/contrast/agent/reaction_processor.rb +1 -1
  39. data/lib/contrast/agent/request.rb +5 -2
  40. data/lib/contrast/agent/request_context.rb +19 -22
  41. data/lib/contrast/agent/static_analysis.rb +1 -1
  42. data/lib/contrast/agent/tracepoint_hook.rb +6 -1
  43. data/lib/contrast/agent/version.rb +1 -1
  44. data/lib/contrast/api/communication/messaging_queue.rb +12 -6
  45. data/lib/contrast/api/communication/service_lifecycle.rb +4 -1
  46. data/lib/contrast/api/communication/socket_client.rb +4 -4
  47. data/lib/contrast/api/decorators/agent_startup.rb +4 -4
  48. data/lib/contrast/api/decorators/application_startup.rb +6 -5
  49. data/lib/contrast/api/decorators/route_coverage.rb +24 -1
  50. data/lib/contrast/components/agent.rb +5 -2
  51. data/lib/contrast/components/assess.rb +6 -3
  52. data/lib/contrast/components/base.rb +2 -2
  53. data/lib/contrast/components/config.rb +1 -0
  54. data/lib/contrast/components/contrast_service.rb +4 -2
  55. data/lib/contrast/components/logger.rb +13 -8
  56. data/lib/contrast/components/scope.rb +9 -28
  57. data/lib/contrast/config/base_configuration.rb +14 -6
  58. data/lib/contrast/configuration.rb +19 -15
  59. data/lib/contrast/extension/assess/array.rb +1 -11
  60. data/lib/contrast/extension/assess/eval_trigger.rb +0 -20
  61. data/lib/contrast/extension/assess/fiber.rb +0 -11
  62. data/lib/contrast/extension/assess/hash.rb +0 -10
  63. data/lib/contrast/extension/assess/kernel.rb +1 -10
  64. data/lib/contrast/extension/assess/marshal.rb +3 -11
  65. data/lib/contrast/extension/assess/regexp.rb +0 -11
  66. data/lib/contrast/extension/assess/string.rb +1 -26
  67. data/lib/contrast/extension/extension.rb +61 -0
  68. data/lib/contrast/extension/protect/kernel.rb +0 -10
  69. data/lib/contrast/framework/grape/support.rb +174 -0
  70. data/lib/contrast/framework/manager.rb +42 -6
  71. data/lib/contrast/framework/rack/support.rb +1 -1
  72. data/lib/contrast/framework/rails/patch/assess_configuration.rb +0 -1
  73. data/lib/contrast/framework/rails/patch/support.rb +6 -3
  74. data/lib/contrast/framework/rails/railtie.rb +1 -1
  75. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +1 -0
  76. data/lib/contrast/framework/rails/support.rb +60 -13
  77. data/lib/contrast/framework/sinatra/support.rb +1 -1
  78. data/lib/contrast/logger/log.rb +89 -15
  79. data/lib/contrast/utils/io_util.rb +1 -1
  80. data/lib/contrast/utils/ruby_ast_rewriter.rb +16 -13
  81. data/lib/contrast/utils/tag_util.rb +2 -1
  82. data/resources/assess/policy.json +197 -2
  83. data/resources/deadzone/policy.json +10 -0
  84. data/ruby-agent.gemspec +10 -1
  85. metadata +78 -12
  86. 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, []).map(&:first)
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
@@ -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 msg, exc, **kwargs
24
- cs__error(msg, exc, **kwargs)
25
- raise exc if exc && exc.cs__class < Exception
26
- end
27
-
28
- def warn msg, exc, **kwargs
29
- cs__warn(msg, exc, **kwargs)
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
- # to be able to dynamically update level based on updates to TeamServer.
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
- # file and level, assuming they weren't set by local configuration.
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.level&.length&.positive? ? config.level : nil
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
- class IOUtil
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
- node.children.each_with_index do |child_node, index|
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
- location.
47
- expression.
48
- source_buffer.
49
- source[child_node.location.begin.begin_pos...child_node.location.end.end_pos]
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
- # For interpolations that use class, instance, or global variables,
54
- # those are NOT within a begin block, but instead are a ivar, cvar,
55
- # or gvar node, not stripping of interpolation markers required.
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
- # When interpolation includes strings before or after an
61
- # interpolation they are simple :str nodes, in order to preserve
62
- # escaping we need to do a dump of the string value.
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 index == node.children.length - 1
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 those given
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
  }, {