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.
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
  }, {