contrast-agent 7.1.0 → 7.2.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/ext/extconf_common.rb +88 -14
  3. data/lib/contrast/agent/assess/policy/source_method.rb +13 -4
  4. data/lib/contrast/agent/assess/policy/trigger_method.rb +12 -18
  5. data/lib/contrast/agent/excluder/excluder.rb +64 -31
  6. data/lib/contrast/agent/protect/rule/base.rb +4 -6
  7. data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker.rb +1 -1
  8. data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +2 -2
  9. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +1 -1
  10. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +1 -1
  11. data/lib/contrast/agent/protect/rule/deserialization/deserialization.rb +2 -2
  12. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +1 -1
  13. data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +1 -1
  14. data/lib/contrast/agent/protect/rule/utils/filters.rb +6 -6
  15. data/lib/contrast/agent/protect/rule/xxe/xxe.rb +1 -1
  16. data/lib/contrast/agent/reporting/client/interface.rb +132 -0
  17. data/lib/contrast/agent/reporting/client/interface_base.rb +27 -0
  18. data/lib/contrast/agent/reporting/connection_status.rb +0 -1
  19. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +6 -4
  20. data/lib/contrast/agent/reporting/reporter.rb +11 -26
  21. data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +1 -1
  22. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +10 -3
  23. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +47 -6
  24. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +40 -31
  25. data/lib/contrast/agent/reporting/reporting_utilities/resend.rb +144 -0
  26. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +35 -13
  27. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_mode.rb +14 -1
  28. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +11 -11
  29. data/lib/contrast/agent/request/request.rb +27 -12
  30. data/lib/contrast/agent/telemetry/base.rb +18 -19
  31. data/lib/contrast/agent/telemetry/exception/obfuscate.rb +97 -0
  32. data/lib/contrast/agent/telemetry/exception.rb +1 -0
  33. data/lib/contrast/agent/version.rb +1 -1
  34. data/lib/contrast/components/config/sources.rb +6 -5
  35. data/lib/contrast/components/settings.rb +9 -0
  36. data/lib/contrast/config/diagnostics/source_config_value.rb +5 -1
  37. data/lib/contrast/config/diagnostics/tools.rb +4 -4
  38. data/lib/contrast/config/validate.rb +2 -2
  39. data/lib/contrast/configuration.rb +11 -19
  40. data/lib/contrast/framework/grape/support.rb +1 -2
  41. data/lib/contrast/framework/manager.rb +17 -8
  42. data/lib/contrast/framework/rack/support.rb +99 -1
  43. data/lib/contrast/framework/rails/support.rb +1 -2
  44. data/lib/contrast/framework/sinatra/support.rb +1 -2
  45. data/lib/contrast/logger/aliased_logging.rb +18 -9
  46. data/lib/contrast/utils/hash_utils.rb +21 -2
  47. data/lib/contrast/utils/request_utils.rb +14 -0
  48. data/resources/assess/policy.json +11 -0
  49. metadata +6 -3
  50. data/lib/contrast/agent/reporting/input_analysis/details/bot_blocker_details.rb +0 -27
@@ -81,11 +81,11 @@ module Contrast
81
81
  # Overlay CLI options - they take precedence over config file
82
82
  cli_options = Contrast::Utils::HashUtils.deep_symbolize_all_keys(cli_options)
83
83
  if cli_options
84
- config_kv = Contrast::Utils::HashUtils.deep_merge(cli_options, config_kv)
84
+ config_kv = Contrast::Utils::HashUtils.precedence_merge(cli_options, config_kv)
85
85
  @_source_file_extensions = Contrast::Utils::HashUtils.
86
- deep_merge(assign_source_to(cli_options,
87
- Contrast::Components::Config::Sources::COMMAND_LINE),
88
- @_source_file_extensions)
86
+ precedence_merge(assign_source_to(cli_options,
87
+ Contrast::Components::Config::Sources::COMMAND_LINE),
88
+ @_source_file_extensions)
89
89
  end
90
90
 
91
91
  # Some in-flight rewrites to maintain backwards compatibility
@@ -157,7 +157,7 @@ module Contrast
157
157
  @_configuration_paths ||= begin
158
158
  basename = default_name.split('.').first
159
159
  # Order of extensions comes from here:
160
- extensions = Contrast::Components::Config::Sources::APP_CONFIGURATION_FILE.map(&:downcase)
160
+ extensions = Contrast::Components::Config::Sources::APP_CONFIGURATION_EXTENSIONS
161
161
 
162
162
  paths = []
163
163
  # Environment paths takes precedence here. Look first through them.
@@ -216,7 +216,6 @@ module Contrast
216
216
  end
217
217
  origin.add_source_file(path, (yaml_to_hash(path) || {}))
218
218
  end
219
-
220
219
  # Legacy usage: Assign main configuration file for reference.
221
220
  @config_file = origin.main_file
222
221
  # merge all settings keeping the top yaml files values as priority.
@@ -225,13 +224,15 @@ module Contrast
225
224
  # precedence of paths: see Contrast::Configuration::CONFIG_BASE_PATHS
226
225
  extensions_maps = []
227
226
  origin.source_files.each do |file|
228
- # config.merge!(file.values) { |_key, oldval, _newval| oldval = oldval }
229
- precedence_merge!(config, file.values)
227
+ config = Contrast::Utils::HashUtils.precedence_merge(config, file.values)
230
228
  # assign source values extentions:
231
229
  extensions_maps << assign_source_to(Contrast::Utils::HashUtils.deep_symbolize_all_keys(file.values), file.path)
232
230
  end
231
+
233
232
  # merge all origin paths to be used as extension classification to preserve the precedence of config files:
234
- extensions_maps.each { |path| @_source_file_extensions = precedence_merge!(@_source_file_extensions, path) }
233
+ extensions_maps.each do |path|
234
+ @_source_file_extensions = Contrast::Utils::HashUtils.precedence_merge!(@_source_file_extensions, path)
235
+ end
235
236
 
236
237
  config
237
238
  end
@@ -357,7 +358,7 @@ module Contrast
357
358
  KEYS_TO_REDACT.include?(key.to_sym)
358
359
  end
359
360
 
360
- def assign_source_to hash, source = Contrast::Components::Config::Sources::APP_CONFIGURATION_FILE[0]
361
+ def assign_source_to hash, source = Contrast::Components::Config::Sources::APP_CONFIGURATION_FILE
361
362
  hash.transform_values do |value|
362
363
  if value.is_a?(Hash)
363
364
  assign_source_to(value, source)
@@ -366,14 +367,5 @@ module Contrast
366
367
  end
367
368
  end
368
369
  end
369
-
370
- # Merges two hashes, first hash will preserve it's values and will only add unique values.
371
- #
372
- # @param hsh [Hash]
373
- # @param other_hsh [Hash]
374
- # @return [Hash]
375
- def precedence_merge! hsh, other_hsh
376
- hsh.merge!(other_hsh) { |_key, old_val, _new_val| old_val }
377
- end
378
370
  end
379
371
  end
@@ -72,8 +72,7 @@ module Contrast
72
72
 
73
73
  # @param request [Contrast::Agent::Request] a contrast tracked request.
74
74
  # @param controller [::Grape::API] optionally use this controller instead of global ::Grape::API.
75
- # @return [Contrast::Agent::Reporting::RouteCoverage, nil] a Dtm describing the route
76
- # matched to the request if a match was found.
75
+ # @return [Contrast::Agent::Reporting::RouteCoverage, nil] the route coverage object or nil if no route
77
76
  def current_route_coverage request, controller = ::Grape::API, full_route = nil
78
77
  return unless grape_controller?(controller)
79
78
 
@@ -37,6 +37,9 @@ module Contrast
37
37
  logger.info('Framework detected. Enabling support.', framework: framework_klass.detection_class)
38
38
  framework_klass
39
39
  end
40
+
41
+ # Delete Rack if we have more than one framework detected
42
+ @_frameworks.delete(Contrast::Framework::Rack::Support) if @_frameworks.length > 1
40
43
  @_frameworks.compact!
41
44
  end
42
45
 
@@ -87,16 +90,22 @@ module Contrast
87
90
  # this particular Request
88
91
  # @return [::Rack::Request] either a rack request or subclass thereof.
89
92
  def retrieve_request env
90
- # If we're mounted on Rails, use Rails.
91
- if @_frameworks.include?(Contrast::Framework::Rails::Support)
92
- return Contrast::Framework::Rails::Support.retrieve_request(env)
93
+ if Contrast::Utils::DuckUtils.empty_duck?(@_frameworks)
94
+ return Contrast::Framework::Rack::Support.retrieve_request(env)
93
95
  end
94
96
 
95
- # If we know the framework, use it.
96
- return @_frameworks[0].retrieve_request(env) if @_frameworks.length == 1
97
-
98
- # Fall back on a regular Rack::Request
99
- ::Rack::Request.new(env)
97
+ framework = @_frameworks[0]
98
+
99
+ case framework.cs__name
100
+ when 'Contrast::Framework::Rails::Support'
101
+ Contrast::Framework::Rails::Support.retrieve_request(env)
102
+ when 'Contrast::Framework::Grape::Support'
103
+ Contrast::Framework::Grape::Support.retrieve_request(env)
104
+ when 'Contrast::Framework::Sinatra::Support'
105
+ Contrast::Framework::Sinatra::Support.retrieve_request(env)
106
+ else
107
+ Contrast::Framework::Rack::Support.retrieve_request(env)
108
+ end
100
109
  rescue StandardError => e
101
110
  logger.warn('Unable to retrieve_request', e)
102
111
  end
@@ -14,7 +14,105 @@ module Contrast
14
14
  extend Contrast::Framework::Rack::Patch::Support
15
15
  class << self
16
16
  def detection_class
17
- 'rack -- don\'t let me be detected'
17
+ 'Rack'
18
+ end
19
+
20
+ # @return [String] the Rack version
21
+ def version
22
+ ::Rack.version
23
+ rescue StandardError
24
+ ''
25
+ end
26
+
27
+ # @return [String] the Rack application name
28
+ def application_name
29
+ 'Rack Application'
30
+ end
31
+
32
+ def application_root
33
+ Dir.pwd
34
+ end
35
+
36
+ # @return [String] the server type
37
+ def server_type
38
+ 'Rack'
39
+ end
40
+
41
+ # Find all the predefined routes for this application
42
+ #
43
+ # Extracting the Rack application routes is not trivial. Routes are evaluated dynamically
44
+ # when a request comes in, so they are not loaded before and stored in a data structure
45
+ # available somewhere. This mean that route discovery is only available through the rack map,
46
+ # but this is limited as not showing the actual method (GET, POST, etc...). For now The Agent
47
+ # will use only the current_route_coverage for Rack applications.
48
+ #
49
+ # @return [Array<Contrast::Agent::Reporting::DiscoveredRoute>]
50
+ # @raise [NoMethodError] raises error if subclass does not implement this method
51
+ def collect_routes
52
+ # return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless defined?(Rack)
53
+ # Rack::URLMap is used for mapping different rack apps to different paths.
54
+ # The Rack app could be separated into smaller rack applications.
55
+ # Rack::Builder is another option.
56
+ # return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless rack_map
57
+
58
+ # This method is disabled for now, as it is not returning the actual routes. Code is left for as
59
+ # comment for future reference.
60
+ #
61
+ # routes = []
62
+ # rack_map.any? do |path, meta|
63
+ # routes << Contrast::Agent::Reporting::DiscoveredRoute.from_rack_route(meta[1], meta[0], path)
64
+ # end
65
+ # routes
66
+ Contrast::Utils::ObjectShare::EMPTY_ARRAY
67
+ end
68
+
69
+ # Given the current request - return a RouteCoverage object
70
+
71
+ # @param request [Contrast::Agent::Request] a contrast tracked request.
72
+ # @param _controller [::Sinatra::Base] optionally use this controller instead of global ::Sinatra::Base.
73
+ # @return [Contrast::Agent::Reporting::RouteCoverage, nil] the route coverage object or nil if no route
74
+ def current_route_coverage request, _controller = nil, full_route = nil
75
+ method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
76
+
77
+ full_route ||= request.env[::Rack::PATH_INFO]
78
+ return unless full_route && method
79
+
80
+ route_coverage = Contrast::Agent::Reporting::RouteCoverage.new
81
+ # We might not have controller, or even if there is defined one, it could not bare the name of the
82
+ # route to match as an object, it could be one router class with base controller with several methods
83
+ # describing each class, search for final controller might be resource heavy, and not efficient.
84
+ # For now to identify the controller the Agent will use the route name, this may lead to recording
85
+ # of false routes, but it is better than nothing. If route do no match a pattern it is a good practice
86
+ # to notify the user by displaying a not found page, in a sense this is a exercise of the application, but
87
+ # not correctly recorded controller name. Try to see if there is a define Rack::URLMap, and use it first.
88
+ mapped_controller = rack_map[full_route]&.last
89
+ final_controller = mapped_controller || full_route
90
+ route_coverage.attach_rack_based_data(final_controller, method, nil, full_route)
91
+ route_coverage
92
+ end
93
+
94
+ # Try and get map of Rack application { "path" => ["pattern", "controller"] }.
95
+ #
96
+ # @return [Hash<String, Array<String>>] the rack map
97
+ def rack_map
98
+ rack_map = {}
99
+ maps = ObjectSpace.each_object(::Rack::URLMap).to_a
100
+ maps.any? do |map|
101
+ mapping = map.instance_variable_get(:@mapping)
102
+ mapping.any? do |arr|
103
+ path = arr[1]
104
+ pattern = arr[2]
105
+ controller = arr[3]&.cs__class&.cs__name
106
+ rack_map[path] = [pattern, controller] if path&.cs__is_a?(String) && controller
107
+ end
108
+ end
109
+ rack_map
110
+ rescue StandardError
111
+ {}
112
+ end
113
+
114
+ def retrieve_request env
115
+ ::Rack::Request.new(env)
18
116
  end
19
117
  end
20
118
  end
@@ -51,8 +51,7 @@ module Contrast
51
51
  # Find the current route, based on the provided Request wrapper
52
52
  #
53
53
  # @param request[Contrast::Agent::Request]
54
- # @return [Contrast::Agent::Reporting::RouteCoverage, nil] a Dtm describing the route
55
- # matched to the request if a match was found.
54
+ # @return [Contrast::Agent::Reporting::RouteCoverage, nil] the route coverage object or nil if no route
56
55
  def current_route_coverage request
57
56
  return unless ::Rails.cs__respond_to?(:application)
58
57
 
@@ -68,8 +68,7 @@ module Contrast
68
68
 
69
69
  # @param request [Contrast::Agent::Request] a contrast tracked request.
70
70
  # @param _controller [::Sinatra::Base] optionally use this controller instead of global ::Sinatra::Base.
71
- # @return [Contrast::Agent::Reporting::RouteCoverage, nil] a Dtm describing the route
72
- # matched to the request if a match was found.
71
+ # @return [Contrast::Agent::Reporting::RouteCoverage, nil] the route coverage object or nil if no route
73
72
  def current_route_coverage request, _controller = ::Sinatra::Base, full_route = nil
74
73
  method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
75
74
  route = _cleaned_route(request)
@@ -72,13 +72,11 @@ module Contrast
72
72
  def build_exception type, message = nil, exception = nil, data = nil
73
73
  return unless buildable?
74
74
 
75
- stack_trace = wrapped_caller_locations
76
- caller_idx = stack_trace&.find_index { |stack| stack.to_s.include?(type) } || 0
77
- # The caller_stack is the method in which the error occurred, so has to be above this method
75
+ caller_idx = wrapped_caller_locations&.find_index { |stack| stack.to_s.include?(type) } || 0
78
76
  caller_idx += 1
79
- caller_frame = stack_trace[caller_idx]
80
- stack_frame_type = caller_frame.path.delete_prefix(Dir.pwd)
81
- stack_frame_function = caller_frame.label
77
+ caller = wrapped_caller_locations[caller_idx]
78
+ stack_frame_type = obfuscate_type(caller)
79
+ stack_frame_function = caller.label
82
80
  key = "#{ stack_frame_type }|#{ stack_frame_function }|#{ message }"
83
81
  if Contrast::TELEMETRY_EXCEPTIONS[key]
84
82
  Contrast::TELEMETRY_EXCEPTIONS.increment(key)
@@ -92,7 +90,7 @@ module Contrast
92
90
  stack_frame_type, message_exception_type,
93
91
  data, exception,
94
92
  message)
95
- build_stack(event_message, stack_trace, caller_idx)
93
+ build_stack(event_message, wrapped_caller_locations, caller_idx)
96
94
  TELEMETRY_EXCEPTIONS[key] = event_message
97
95
  rescue StandardError => e
98
96
  debug('[Telemetry] Unable to report exception', e)
@@ -141,8 +139,11 @@ module Contrast
141
139
  caller_stack.each_with_index do |caller, idx|
142
140
  next unless idx > caller_idx
143
141
 
144
- stack_frame = Contrast::Agent::Telemetry::Exception::StackFrame.build(caller.label,
145
- caller.path.delete_prefix(Dir.pwd))
142
+ obfuscated_label = Contrast::Agent::Telemetry::Exception::Obfuscate.obfuscate_path(caller.label)
143
+ obfuscated_path = Contrast::Agent::Telemetry::Exception::Obfuscate.
144
+ obfuscate_path(caller.path.delete_prefix(Dir.pwd))
145
+
146
+ stack_frame = Contrast::Agent::Telemetry::Exception::StackFrame.build(obfuscated_label, obfuscated_path)
146
147
  event_exception_message.push(stack_frame)
147
148
  end
148
149
  end
@@ -153,6 +154,14 @@ module Contrast
153
154
  def wrapped_caller_locations
154
155
  caller_locations
155
156
  end
157
+
158
+ # @param caller [Thread::Backtrace::Location, nil]
159
+ # @return [String]
160
+ def obfuscate_type caller
161
+ return '' unless caller.cs__respond_to?(:path)
162
+
163
+ Contrast::Agent::Telemetry::Exception::Obfuscate.obfuscate_path(caller.path.delete_prefix(Dir.pwd).to_s)
164
+ end
156
165
  end
157
166
  end
158
167
  end
@@ -10,9 +10,28 @@ module Contrast
10
10
  #
11
11
  # @param hsh [Hash]
12
12
  # @param other_hsh [Hash]
13
- def deep_merge hsh, other_hsh
13
+ def precedence_merge hsh, other_hsh
14
14
  hsh.merge(other_hsh) do |_key, old_value, new_value|
15
- old_value.is_a?(Hash) || new_value.is_a?(Hash) ? deep_merge(old_value, new_value) : old_value
15
+ if old_value.is_a?(Hash) || new_value.is_a?(Hash)
16
+ Contrast::Utils::HashUtils.precedence_merge(old_value, new_value)
17
+ else
18
+ old_value
19
+ end
20
+ end
21
+ end
22
+
23
+ # Merges two hashes, first hash will preserve it's values and will only add unique values.
24
+ #
25
+ # @param hsh [Hash]
26
+ # @param other_hsh [Hash]
27
+ # @return [Hash]
28
+ def precedence_merge! hsh, other_hsh
29
+ hsh.merge!(other_hsh) do |_key, old_val, new_val|
30
+ if old_val.is_a?(Hash) || new_val.is_a?(Hash)
31
+ Contrast::Utils::HashUtils.precedence_merge!(old_val, new_val)
32
+ else
33
+ old_val
34
+ end
16
35
  end
17
36
  end
18
37
 
@@ -5,6 +5,20 @@ module Contrast
5
5
  module Utils
6
6
  # used in Contrast::Agent::Request
7
7
  module RequestUtils
8
+ # TOKENS:
9
+ NUM_ = '/{n}/'
10
+ ID_ = '{ID}'
11
+ # PATTERNS:
12
+ NUM_PATTERN = %r{/\d+/}.cs__freeze
13
+ END_PATTERN = %r{/\d+$}.cs__freeze
14
+ STATIC_SUFFIXES = /\.(?:js|css|jpeg|jpg|gif|png|ico|woff|svg|pdf|eot|ttf|jar)$/i.cs__freeze
15
+ UUID_PATTERN = Regexp.new('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}').cs__freeze # rubocop:disable Metrics/LineLength
16
+ # Regular expression to match any type of hash pattern that is 16 bytes like uuid with no
17
+ # slashes, md5, sha1, sha256, etc
18
+ HASH_PATTERN = Regexp.new('([a-fA-F0-9]{2}){16,}').cs__freeze
19
+ WIN_PATTERN = Regexp.new('S-1-5-((32-\d+)|(21-\d+-\d+-\d+-\d+))').cs__freeze
20
+ MEDIA_TYPE_MARKERS = %w[image/ text/css text/javascript].cs__freeze
21
+
8
22
  # Return a flattened hash of params with realized paths for keys, in
9
23
  # addition to a separate, valueless, entry for each nest key.
10
24
  # See RUBY-621 for more details.
@@ -1258,6 +1258,17 @@
1258
1258
  "tags":["HTML_ENCODED"],
1259
1259
  "untags":["HTML_DECODED"]
1260
1260
  },
1261
+ {
1262
+ "class_name": "Rails::HTML::Concern::ComposedSanitize",
1263
+ "method_name": "sanitize",
1264
+ "method_visibility": "public",
1265
+ "instance_method": true,
1266
+ "source": "P0",
1267
+ "target": "R",
1268
+ "action": "REMOVE",
1269
+ "tags":["HTML_ENCODED"],
1270
+ "untags":["HTML_DECODED"]
1271
+ },
1261
1272
  {
1262
1273
  "class_name": "Rails::Html::SafeListSanitizer",
1263
1274
  "method_name": "sanitize",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrast-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0
4
+ version: 7.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - galen.palmer@contrastsecurity.com
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: exe
15
15
  cert_chain: []
16
- date: 2023-04-13 00:00:00.000000000 Z
16
+ date: 2023-05-31 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -1051,6 +1051,8 @@ files:
1051
1051
  - lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb
1052
1052
  - lib/contrast/agent/reporting/attack_result/response_type.rb
1053
1053
  - lib/contrast/agent/reporting/attack_result/user_input.rb
1054
+ - lib/contrast/agent/reporting/client/interface.rb
1055
+ - lib/contrast/agent/reporting/client/interface_base.rb
1054
1056
  - lib/contrast/agent/reporting/connection_status.rb
1055
1057
  - lib/contrast/agent/reporting/details/bot_blocker_details.rb
1056
1058
  - lib/contrast/agent/reporting/details/cmd_injection_details.rb
@@ -1069,7 +1071,6 @@ files:
1069
1071
  - lib/contrast/agent/reporting/details/xxe_details.rb
1070
1072
  - lib/contrast/agent/reporting/details/xxe_match.rb
1071
1073
  - lib/contrast/agent/reporting/details/xxe_wrapper.rb
1072
- - lib/contrast/agent/reporting/input_analysis/details/bot_blocker_details.rb
1073
1074
  - lib/contrast/agent/reporting/input_analysis/details/protect_rule_details.rb
1074
1075
  - lib/contrast/agent/reporting/input_analysis/input_analysis.rb
1075
1076
  - lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb
@@ -1130,6 +1131,7 @@ files:
1130
1131
  - lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb
1131
1132
  - lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb
1132
1133
  - lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb
1134
+ - lib/contrast/agent/reporting/reporting_utilities/resend.rb
1133
1135
  - lib/contrast/agent/reporting/reporting_utilities/response.rb
1134
1136
  - lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb
1135
1137
  - lib/contrast/agent/reporting/reporting_utilities/response_handler.rb
@@ -1181,6 +1183,7 @@ files:
1181
1183
  - lib/contrast/agent/telemetry/exception/event.rb
1182
1184
  - lib/contrast/agent/telemetry/exception/message.rb
1183
1185
  - lib/contrast/agent/telemetry/exception/message_exception.rb
1186
+ - lib/contrast/agent/telemetry/exception/obfuscate.rb
1184
1187
  - lib/contrast/agent/telemetry/exception/stack_frame.rb
1185
1188
  - lib/contrast/agent/telemetry/hash.rb
1186
1189
  - lib/contrast/agent/telemetry/identifier.rb
@@ -1,27 +0,0 @@
1
- # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
- # frozen_string_literal: true
3
-
4
- require 'contrast/agent/reporting/input_analysis/details/protect_rule_details'
5
-
6
- module Contrast
7
- module Agent
8
- module Reporting
9
- # Bot blocker IA result details info.
10
- class BotBlockerDetails < ProtectRuleDetails
11
- # @return [String]
12
- attr_accessor :bot
13
- # User agent header value
14
- #
15
- # @return [String]
16
- attr_accessor :user_agent
17
-
18
- def to_controlled_hash
19
- {
20
- bot: bot,
21
- userAgent: user_agent
22
- }
23
- end
24
- end
25
- end
26
- end
27
- end