contrast-agent 7.1.0 → 7.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/extconf_common.rb +88 -14
- data/lib/contrast/agent/assess/policy/source_method.rb +13 -4
- data/lib/contrast/agent/assess/policy/trigger_method.rb +12 -18
- data/lib/contrast/agent/excluder/excluder.rb +64 -31
- data/lib/contrast/agent/protect/rule/base.rb +4 -6
- data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker.rb +1 -1
- data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +2 -2
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +1 -1
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization/deserialization.rb +2 -2
- data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +1 -1
- data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +1 -1
- data/lib/contrast/agent/protect/rule/utils/filters.rb +6 -6
- data/lib/contrast/agent/protect/rule/xxe/xxe.rb +1 -1
- data/lib/contrast/agent/reporting/client/interface.rb +132 -0
- data/lib/contrast/agent/reporting/client/interface_base.rb +27 -0
- data/lib/contrast/agent/reporting/connection_status.rb +0 -1
- data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +6 -4
- data/lib/contrast/agent/reporting/reporter.rb +11 -26
- data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +10 -3
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +47 -6
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +40 -31
- data/lib/contrast/agent/reporting/reporting_utilities/resend.rb +144 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +35 -13
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_mode.rb +14 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +11 -11
- data/lib/contrast/agent/request/request.rb +27 -12
- data/lib/contrast/agent/telemetry/base.rb +18 -19
- data/lib/contrast/agent/telemetry/exception/obfuscate.rb +97 -0
- data/lib/contrast/agent/telemetry/exception.rb +1 -0
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/components/config/sources.rb +6 -5
- data/lib/contrast/components/settings.rb +9 -0
- data/lib/contrast/config/diagnostics/source_config_value.rb +5 -1
- data/lib/contrast/config/diagnostics/tools.rb +4 -4
- data/lib/contrast/config/validate.rb +2 -2
- data/lib/contrast/configuration.rb +11 -19
- data/lib/contrast/framework/grape/support.rb +1 -2
- data/lib/contrast/framework/manager.rb +17 -8
- data/lib/contrast/framework/rack/support.rb +99 -1
- data/lib/contrast/framework/rails/support.rb +1 -2
- data/lib/contrast/framework/sinatra/support.rb +1 -2
- data/lib/contrast/logger/aliased_logging.rb +18 -9
- data/lib/contrast/utils/hash_utils.rb +21 -2
- data/lib/contrast/utils/request_utils.rb +14 -0
- data/resources/assess/policy.json +11 -0
- metadata +6 -3
- 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.
|
84
|
+
config_kv = Contrast::Utils::HashUtils.precedence_merge(cli_options, config_kv)
|
85
85
|
@_source_file_extensions = Contrast::Utils::HashUtils.
|
86
|
-
|
87
|
-
|
88
|
-
|
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::
|
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
|
-
|
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
|
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
|
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]
|
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
|
-
|
91
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
'
|
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]
|
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]
|
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
|
-
|
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
|
-
|
80
|
-
stack_frame_type =
|
81
|
-
stack_frame_function =
|
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,
|
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
|
-
|
145
|
-
|
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
|
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)
|
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.
|
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-
|
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
|