contrast-agent 6.6.5 → 6.7.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 (150) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.gitmodules +0 -3
  4. data/ext/cs__scope/cs__scope.c +1 -1
  5. data/lib/contrast/agent/assess/contrast_event.rb +2 -24
  6. data/lib/contrast/agent/assess/events/source_event.rb +7 -61
  7. data/lib/contrast/agent/assess/finalizers/hash.rb +11 -0
  8. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +0 -55
  9. data/lib/contrast/agent/assess/policy/policy_node.rb +3 -3
  10. data/lib/contrast/agent/assess/policy/policy_node_utils.rb +0 -1
  11. data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
  12. data/lib/contrast/agent/assess/policy/source_method.rb +24 -1
  13. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -5
  14. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +6 -1
  15. data/lib/contrast/agent/assess/policy/trigger_method.rb +36 -132
  16. data/lib/contrast/agent/assess/policy/trigger_node.rb +3 -3
  17. data/lib/contrast/agent/assess/property/evented.rb +2 -12
  18. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +42 -84
  19. data/lib/contrast/agent/assess/rule/response/base_rule.rb +11 -27
  20. data/lib/contrast/agent/assess/rule/response/body_rule.rb +1 -3
  21. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +77 -62
  22. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +1 -1
  23. data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +6 -1
  24. data/lib/contrast/agent/assess/rule/response/header_rule.rb +5 -5
  25. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +1 -1
  26. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +1 -1
  27. data/lib/contrast/agent/assess/tracker.rb +1 -7
  28. data/lib/contrast/agent/excluder.rb +206 -0
  29. data/lib/contrast/agent/exclusion_matcher.rb +6 -0
  30. data/lib/contrast/agent/inventory/database_config.rb +6 -10
  31. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +4 -0
  32. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -0
  33. data/lib/contrast/agent/protect/rule/base.rb +49 -5
  34. data/lib/contrast/agent/protect/rule/base_service.rb +1 -0
  35. data/lib/contrast/agent/protect/rule/cmd_injection.rb +18 -105
  36. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +129 -0
  37. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +169 -0
  38. data/lib/contrast/agent/protect/rule/deserialization.rb +2 -1
  39. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +51 -0
  40. data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +67 -0
  41. data/lib/contrast/agent/protect/rule/sqli.rb +6 -31
  42. data/lib/contrast/agent/protect/rule/xxe.rb +2 -0
  43. data/lib/contrast/agent/protect/rule.rb +3 -1
  44. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +6 -0
  45. data/lib/contrast/agent/reporting/details/sqli_dangerous_functions.rb +22 -0
  46. data/lib/contrast/agent/reporting/reporter.rb +1 -2
  47. data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +2 -2
  48. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +1 -4
  49. data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +1 -1
  50. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +0 -23
  51. data/lib/contrast/agent/reporting/reporting_events/finding.rb +19 -49
  52. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +12 -9
  53. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +1 -1
  54. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +23 -21
  55. data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +5 -18
  56. data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +1 -0
  57. data/lib/contrast/{api/decorators/trace_taint_range_tags.rb → agent/reporting/reporting_events/finding_event_taint_range_tags.rb} +7 -6
  58. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +1 -1
  59. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +1 -1
  60. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +2 -2
  61. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -14
  62. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +11 -0
  63. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +3 -1
  64. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +11 -23
  65. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +8 -26
  66. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -1
  67. data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +4 -7
  68. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -1
  69. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +3 -3
  70. data/lib/contrast/agent/request.rb +2 -2
  71. data/lib/contrast/agent/request_context.rb +8 -20
  72. data/lib/contrast/agent/request_context_extend.rb +15 -36
  73. data/lib/contrast/agent/request_handler.rb +0 -8
  74. data/lib/contrast/agent/response.rb +0 -18
  75. data/lib/contrast/agent/telemetry/events/event.rb +1 -1
  76. data/lib/contrast/agent/telemetry/events/metric_event.rb +1 -1
  77. data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +3 -3
  78. data/lib/contrast/agent/version.rb +1 -1
  79. data/lib/contrast/api/communication/messaging_queue.rb +2 -3
  80. data/lib/contrast/api/communication/socket_client.rb +4 -4
  81. data/lib/contrast/api/communication/speedracer.rb +4 -8
  82. data/lib/contrast/api/decorators/agent_startup.rb +5 -6
  83. data/lib/contrast/api/decorators/application_settings.rb +2 -1
  84. data/lib/contrast/api/decorators/application_startup.rb +6 -6
  85. data/lib/contrast/api/decorators/message.rb +0 -4
  86. data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -6
  87. data/lib/contrast/api/decorators.rb +0 -6
  88. data/lib/contrast/api/dtm.pb.rb +0 -489
  89. data/lib/contrast/components/agent.rb +16 -12
  90. data/lib/contrast/components/api.rb +10 -10
  91. data/lib/contrast/components/app_context.rb +3 -3
  92. data/lib/contrast/components/app_context_extend.rb +1 -1
  93. data/lib/contrast/components/assess.rb +92 -38
  94. data/lib/contrast/components/assess_rules.rb +36 -0
  95. data/lib/contrast/components/config.rb +54 -12
  96. data/lib/contrast/components/contrast_service.rb +8 -8
  97. data/lib/contrast/components/heap_dump.rb +1 -1
  98. data/lib/contrast/components/protect.rb +5 -5
  99. data/lib/contrast/components/ruby_component.rb +81 -0
  100. data/lib/contrast/components/sampling.rb +1 -1
  101. data/lib/contrast/components/security_logger.rb +23 -0
  102. data/lib/contrast/components/service.rb +55 -0
  103. data/lib/contrast/components/settings.rb +12 -4
  104. data/lib/contrast/config/base_configuration.rb +1 -1
  105. data/lib/contrast/config/protect_rules_configuration.rb +17 -3
  106. data/lib/contrast/config/server_configuration.rb +1 -1
  107. data/lib/contrast/config.rb +0 -6
  108. data/lib/contrast/configuration.rb +81 -17
  109. data/lib/contrast/extension/assess/exec_trigger.rb +3 -1
  110. data/lib/contrast/extension/assess/marshal.rb +3 -2
  111. data/lib/contrast/extension/assess/string.rb +0 -1
  112. data/lib/contrast/extension/extension.rb +1 -1
  113. data/lib/contrast/framework/base_support.rb +0 -5
  114. data/lib/contrast/framework/grape/support.rb +1 -23
  115. data/lib/contrast/framework/manager.rb +0 -10
  116. data/lib/contrast/framework/rails/support.rb +5 -58
  117. data/lib/contrast/framework/sinatra/support.rb +2 -21
  118. data/lib/contrast/logger/cef_log.rb +21 -3
  119. data/lib/contrast/logger/log.rb +1 -11
  120. data/lib/contrast/tasks/config.rb +4 -2
  121. data/lib/contrast/utils/assess/event_limit_utils.rb +5 -8
  122. data/lib/contrast/utils/assess/trigger_method_utils.rb +10 -18
  123. data/lib/contrast/utils/findings.rb +6 -5
  124. data/lib/contrast/utils/hash_digest.rb +9 -24
  125. data/lib/contrast/utils/hash_digest_extend.rb +6 -6
  126. data/lib/contrast/utils/invalid_configuration_util.rb +21 -58
  127. data/lib/contrast/utils/log_utils.rb +32 -8
  128. data/lib/contrast/utils/net_http_base.rb +2 -2
  129. data/lib/contrast/utils/patching/policy/patch_utils.rb +3 -2
  130. data/lib/contrast/utils/stack_trace_utils.rb +0 -25
  131. data/lib/contrast/utils/string_utils.rb +9 -0
  132. data/lib/contrast/utils/telemetry_client.rb +13 -7
  133. data/lib/contrast.rb +5 -10
  134. metadata +22 -28
  135. data/lib/contrast/agent/reporting/reporting_events/trace_event_source.rb +0 -30
  136. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -36
  137. data/lib/contrast/api/decorators/activity.rb +0 -33
  138. data/lib/contrast/api/decorators/architecture_component.rb +0 -36
  139. data/lib/contrast/api/decorators/finding.rb +0 -29
  140. data/lib/contrast/api/decorators/route_coverage.rb +0 -91
  141. data/lib/contrast/api/decorators/trace_event.rb +0 -120
  142. data/lib/contrast/api/decorators/trace_event_object.rb +0 -63
  143. data/lib/contrast/api/decorators/trace_event_signature.rb +0 -69
  144. data/lib/contrast/api/decorators/trace_taint_range.rb +0 -52
  145. data/lib/contrast/config/assess_configuration.rb +0 -93
  146. data/lib/contrast/config/assess_rules_configuration.rb +0 -32
  147. data/lib/contrast/config/root_configuration.rb +0 -90
  148. data/lib/contrast/config/ruby_configuration.rb +0 -81
  149. data/lib/contrast/config/service_configuration.rb +0 -49
  150. data/lib/contrast/utils/preflight_util.rb +0 -13
@@ -1,9 +1,10 @@
1
1
  # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'contrast/agent/reporting/reporting_events/reporting_event'
4
5
  require 'contrast/components/assess'
5
6
  require 'contrast/components/logger'
6
- require 'contrast/agent/reporting/reporting_events/reporting_event'
7
+ require 'contrast/utils/string_utils'
7
8
 
8
9
  module Contrast
9
10
  module Agent
@@ -13,6 +14,8 @@ module Contrast
13
14
  # identifying information of a Finding/Trace, which TeamServer will use to determine if it requires the full
14
15
  # information of the Finding/Trace to be reported.
15
16
  class PreflightMessage
17
+ include Contrast::Components::Logger::InstanceMethods
18
+
16
19
  # @return [String] the message identifier; rule_id,hash
17
20
  attr_accessor :data
18
21
  # @return [String] CRC checksum of the finding to which this message pertains
@@ -26,9 +29,6 @@ module Contrast
26
29
  CODE = :TRACE
27
30
 
28
31
  def initialize
29
- @app_language = Contrast::Utils::ObjectShare::RUBY
30
- @app_name = ::Contrast::APP_CONTEXT.name # rubocop:disable Security/Module/Name
31
- @app_version = ::Contrast::APP_CONTEXT.version
32
32
  @routes = []
33
33
  end
34
34
 
@@ -47,24 +47,20 @@ module Contrast
47
47
 
48
48
  {
49
49
  code: CODE,
50
- app_language: @app_language,
51
- app_name: @app_name,
52
- app_version: @app_version,
50
+ app_language: Contrast::Utils::ObjectShare::RUBY,
51
+ app_name: ::Contrast::APP_CONTEXT.name, # rubocop:disable Security/Module/Name
52
+ app_version: ::Contrast::APP_CONTEXT.version,
53
53
  data: '',
54
54
  key: 0,
55
- routes: @routes,
55
+ routes: @routes.map(&:to_controlled_hash),
56
56
  session_id: ::Contrast::ASSESS.session_id
57
57
  }
58
58
  end
59
59
 
60
60
  # @raise [ArgumentError]
61
61
  def validate
62
- raise(ArgumentError, "#{ cs__class } did not have a proper data. Unable to continue.") unless data
63
- unless @app_name
64
- raise(ArgumentError, "#{ cs__class } did not have a proper application name. Unable to continue.")
65
- end
66
- unless @app_language
67
- raise(ArgumentError, "#{ cs__class } did not have a proper application language. Unable to continue.")
62
+ unless Contrast::Utils::StringUtils.present?(data)
63
+ raise(ArgumentError, "#{ cs__class } did not have a proper data. Unable to continue.")
68
64
  end
69
65
  unless ::Contrast::ASSESS.session_id
70
66
  raise(ArgumentError, "#{ cs__class } did not have a proper session id. Unable to continue.")
@@ -49,6 +49,17 @@ module Contrast
49
49
 
50
50
  # @raise [ArgumentError]
51
51
  def validate; end
52
+
53
+ # Helper method to get json representation of event and handle errors
54
+ #
55
+ # @return [String] - JSON
56
+ def event_json
57
+ hsh = to_controlled_hash
58
+ hsh.to_json
59
+ rescue Exception => e # rubocop:disable Lint/RescueException
60
+ logger.error('Unable to convert JSON string', e, hsh)
61
+ raise(e)
62
+ end
52
63
  end
53
64
  end
54
65
  end
@@ -42,7 +42,9 @@ module Contrast
42
42
  # @param url [String] the literal url of the route actively being executed
43
43
  # @return [Contrast::Agent::Reporting::RouteCoverage]
44
44
  def attach_rack_based_data final_controller, method, route_pattern, url = nil
45
- if route_pattern.cs__is_a?(Grape::Router::Route)
45
+ if Contrast::Utils::ClassUtil.truly_defined?('Grape::Router::Route') &&
46
+ route_pattern.cs__is_a?(Grape::Router::Route)
47
+
46
48
  safe_pattern = route_pattern.pattern&.path&.to_s
47
49
  safe_url = source_or_string(url || safe_pattern)
48
50
  else
@@ -14,34 +14,22 @@ module Contrast
14
14
  # externally accessible endpoints within the application, as registered to the application framework. They may or
15
15
  # may not have been invoked at the time of reporting.
16
16
  #
17
- # @attr_reader observations [observations] the routes and verbs seen that match to this Route
18
- # @attr_reader signature [String] the unique identifier for this route; typically the method signature. Required
19
- # for reporting.
20
17
  class RouteDiscovery
21
18
  include Contrast::Components::Logger::InstanceMethods
22
19
 
23
- # required attributes
24
- attr_reader :observations, :signature
20
+ # @return [Array<Contrast::Agent::Reporting::RouteDiscoveryObservation>] the routes and verbs seen that match
21
+ # to this Route.
22
+ attr_reader :observations
23
+ # @return [String] the unique identifier for this route; typically the method signature. Required for
24
+ # reporting.
25
+ attr_accessor :signature
25
26
 
26
- class << self
27
- # Convert a DTM for SpeedRacer to an Event for TeamServer.
28
- #
29
- # @param route_coverage_dtm [Contrast::Api::Dtm::RouteCoverage]
30
- # @return [Contrast::Agent::Reporting::RouteDiscovery]
31
- def convert route_coverage_dtm
32
- report = new
33
- report.attach_data(route_coverage_dtm)
34
- report
35
- end
36
- end
37
-
38
- # Attach the data from the protobuf models to this reporter so that it can be sent to TeamServer directly
39
- #
40
- # @param route_coverage_dtm [Contrast::Api::Dtm::RouteCoverage]
41
- def attach_data route_coverage_dtm
42
- @signature = route_coverage_dtm.route
27
+ # @param signature [String]
28
+ # @param observation [Contrast::Agent::Reporting::RouteDiscoveryObservation]
29
+ def initialize signature, observation
30
+ @signature = signature
43
31
  @observations = []
44
- observations << Contrast::Agent::Reporting::RouteDiscoveryObservation.convert(route_coverage_dtm)
32
+ observations << observation
45
33
  end
46
34
 
47
35
  # Convert the instance variables on the class, and other information, into the identifiers required for
@@ -12,36 +12,18 @@ module Contrast
12
12
  # reporting system to relay this information in the Application Update messages. These route observations are
13
13
  # used by TeamServer to construct the route coverage information for the assess feature. They represent the
14
14
  # literal URL and HTTP verb used to invoke a method in the application, as routed by the application framework.
15
- #
16
- # @attr_reader url [String] the URL requested to hit this endpoint. Required for reporting.
17
- # @attr_reader verb [String] the HTTP Method requested to his this endpoint. Empty means all, so is allowed.
18
- # for reporting.
19
15
  class RouteDiscoveryObservation
20
16
  include Contrast::Components::Logger::InstanceMethods
21
17
 
22
- # required attributes
23
- attr_reader :url
24
- # optional attributes
25
- attr_reader :verb
18
+ # @return [String] the URL requested to hit this endpoint. Required for reporting; required attributes
19
+ attr_accessor :url
20
+ # @return [String] the HTTP Method requested to his this endpoint. Empty means all, so is allowed for
21
+ # reporting; optional attributes
22
+ attr_accessor :verb
26
23
 
27
- class << self
28
- # Convert a DTM for SpeedRacer to an Event for TeamServer.
29
- #
30
- # @param route_coverage_dtm [Contrast::Api::Dtm::RouteCoverage]
31
- # @return [Contrast::Agent::Reporting::RouteDiscoveryObservation]
32
- def convert route_coverage_dtm
33
- report = new
34
- report.attach_data(route_coverage_dtm)
35
- report
36
- end
37
- end
38
-
39
- # Attach the data from the protobuf models to this reporter so that it can be sent to TeamServer directly
40
- #
41
- # @param route_coverage_dtm [Contrast::Api::Dtm::RouteCoverage]
42
- def attach_data route_coverage_dtm
43
- @url = route_coverage_dtm.url
44
- @verb = route_coverage_dtm.verb if Contrast::Utils::StringUtils.present?(route_coverage_dtm.verb)
24
+ def initialize url, verb
25
+ @url = url
26
+ @verb = verb if Contrast::Utils::StringUtils.present?(verb)
45
27
  end
46
28
 
47
29
  # Convert the instance variables on the class, and other information, into the identifiers required for
@@ -29,7 +29,7 @@ module Contrast
29
29
  return unless ::Contrast::API.request_audit_requests || ::Contrast::API.request_audit_responses
30
30
 
31
31
  file_name = event.cs__respond_to?(:file_name) ? event.file_name : event.cs__class.cs__name.to_s.downcase
32
- data = event.to_controlled_hash.to_json
32
+ data = event.event_json
33
33
  log_data(:request, file_name, data) if data
34
34
  return unless ::Contrast::API.request_audit_responses
35
35
 
@@ -14,17 +14,14 @@ module Contrast
14
14
  module BuildPreflight
15
15
  class << self
16
16
  # @param finding [Contrast::Agent::Reporting::Finding]
17
- # @param request [Contrast::Agent::Request] current request
18
- def build finding, request
17
+ # @return [Contrast::Agent::Reporting::Preflight, nil]
18
+ def generate finding
19
19
  return unless finding
20
20
 
21
- # save the current finding
22
- Contrast::Agent::Reporting::ReportingStorage[finding.hash_code] = finding
23
-
24
21
  new_preflight = Contrast::Agent::Reporting::Preflight.new
25
22
  new_preflight_message = Contrast::Agent::Reporting::PreflightMessage.new
26
- if request&.route
27
- new_preflight_message.routes << Contrast::Agent::Reporting::RouteDiscovery.convert(request.route)
23
+ finding.routes.each do |route|
24
+ new_preflight_message.routes << route
28
25
  end
29
26
  new_preflight_message.hash_code = finding.hash_code
30
27
  new_preflight_message.data = "#{ finding.rule_id },#{ finding.hash_code }"
@@ -32,7 +32,7 @@ module Contrast
32
32
  @encoding = ENCODING
33
33
  end
34
34
 
35
- def to_hash
35
+ def to_contrast_hash
36
36
  {
37
37
  app_name: @app_name,
38
38
  api_key: @api_key,
@@ -69,7 +69,7 @@ module Contrast
69
69
  # Handles standard error case, logs and set status for failure
70
70
  #
71
71
  # @param event [Contrast::Agent::Reporting::ReportingEvent]
72
- # One of the DTMs valid for the event field of Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
72
+ # One of the DTMs valid for the event field of Contrast::Api::Dtm::Message
73
73
  # @param error_msg [StandardError]
74
74
  # @return nil [NilClass] to be passed as response
75
75
  def handle_error event, error_msg
@@ -105,7 +105,7 @@ module Contrast
105
105
  findings_to_return = response.body.split(',').delete_if { |el| el.include?('*') }
106
106
  findings_to_return.each do |index|
107
107
  preflight_message = event.messages[index.to_i]
108
- corresponding_finding = Contrast::Agent::Reporting::ReportingStorage.delete(preflight_message.hash_code)
108
+ corresponding_finding = Contrast::Agent::Reporting::ReportingStorage.delete(preflight_message.data)
109
109
  next unless corresponding_finding
110
110
 
111
111
  send_event(corresponding_finding, connection)
@@ -130,7 +130,7 @@ module Contrast
130
130
  end
131
131
  build_headers(request)
132
132
  event.attach_headers(request)
133
- request.body = event.to_controlled_hash.to_json
133
+ request.body = event.event_json
134
134
  request
135
135
  end
136
136
  end
@@ -33,10 +33,10 @@ module Contrast
33
33
 
34
34
  # @return [Rack::Request] The passed to the Agent RackRequest to be wrapped.
35
35
  attr_reader :rack_request
36
- # @return [Contrast::Api::Dtm::RouteCoverage] the route, used for findings, of this request
37
- attr_accessor :route
38
36
  # @return [Contrast::Agent::Reporting::ObservedRoute] the route, used for coverage, of this request
39
37
  attr_accessor :observed_route
38
+ # @return [Contrast::Agent::Reporting::RouteDiscovery]
39
+ attr_accessor :discovered_route
40
40
 
41
41
  # Delegate calls to the following methods to the attribute @rack_request
42
42
  def_delegators :@rack_request, :base_url, :cookies, :env, :ip, :media_type, :path, :port, :query_string,
@@ -28,10 +28,6 @@ module Contrast
28
28
 
29
29
  # @return [Contrast::Agent::Reporting:ApplicationActivity] the application activity found in this request
30
30
  attr_reader :activity
31
- # REMOVE once findings and routes are done.
32
- #
33
- # @return [Contrast::Api::Dtm::Activity] the application activity found in this request
34
- attr_reader :dtm_activity
35
31
  # @return [Hash] context used to log the request
36
32
  attr_reader :logging_hash
37
33
  # @return [Contrast::Agent::Reporting::ObservedRoute] the route, used for coverage, of this request
@@ -41,10 +37,12 @@ module Contrast
41
37
  # @return [Contrast::Agent::Response] our wrapper around the Rack::Response or Array for this context,
42
38
  # only available after the application has finished its processing
43
39
  attr_reader :response
44
- # @return [Contrast::Api::Dtm::RouteCoverage] the route, used for findings, of this request
45
- attr_reader :route
40
+ # @return [Contrast::Agent::Reporting::RouteDiscovery] the route, used for findings, of this request
41
+ attr_reader :discovered_route
46
42
  # @return [Contrast::Api::Settings::InputAnalysis] the protect input analysis of sources on this request
47
43
  attr_reader :speedracer_input_analysis
44
+ # @return [Array<String>] the hash of findings already reported fro this request
45
+ attr_reader :reported_findings
48
46
  # @return [Contrast::Utils::Timer] when the context was created
49
47
  attr_reader :timer
50
48
 
@@ -60,12 +58,6 @@ module Contrast
60
58
  @request = Contrast::Agent::Request.new(rack_request)
61
59
  @activity = Contrast::Agent::Reporting::ApplicationActivity.new
62
60
 
63
- # REMOVE once findings and routes are done.
64
- #
65
- # We still need the activity to report routes and findings
66
- @dtm_activity = Contrast::Api::Dtm::Activity.new
67
- @dtm_activity.http_request = request.dtm
68
-
69
61
  # build analyzer
70
62
  @do_not_track = false
71
63
  @speedracer_input_analysis = EMPTY_INPUT_ANALYSIS_PB
@@ -89,6 +81,8 @@ module Contrast
89
81
  @sample_req, @sample_res = Contrast::Utils::Assess::SamplingUtil.instance.sample?(@request)
90
82
  end
91
83
 
84
+ @reported_findings = []
85
+
92
86
  handle_routes
93
87
  end
94
88
  end
@@ -142,14 +136,8 @@ module Contrast
142
136
 
143
137
  def handle_routes
144
138
  @observed_route = Contrast::Agent::Reporting::ObservedRoute.new
145
- # TODO: RUBY-1705 when we no longer need the DTM style, delete this method and use the get_route_information
146
- # instead.
147
- route_dtm = Contrast::Agent.framework_manager.get_route_dtm(@request)
148
- # new_route_coverage_dtm = Contrast::Agent.framework_manager.get_route_information(@request)
149
- # TODO: RUBY-1705 -- delete append_route_coverage
150
- append_route_coverage(route_dtm)
151
- # TODO: RUBY-1705 -- change to take [Contrast::Agent::Reporting::ObservedRoute]
152
- append_to_observed_route(route_dtm)
139
+ reporting_route = Contrast::Agent.framework_manager.get_route_information(@request)
140
+ append_to_observed_route(reporting_route)
153
141
  end
154
142
  end
155
143
  end
@@ -13,6 +13,7 @@ require 'contrast/agent/assess/rule/response/x_xss_protection_header_rule'
13
13
  require 'contrast/agent/protect/input_analyzer/input_analyzer'
14
14
  require 'contrast/components/logger'
15
15
  require 'contrast/utils/log_utils'
16
+ require 'contrast/utils/string_utils'
16
17
 
17
18
  module Contrast
18
19
  module Agent
@@ -24,30 +25,11 @@ module Contrast
24
25
  include Contrast::Components::Logger::InstanceMethods
25
26
  BUILD_ATTACK_LOGGER_MESSAGE = 'Building attack result from Contrast Service input analysis result'
26
27
  CEF_LOGGING_RULES = %w[bot-blocker virtual-patch ip-denylist].cs__freeze
27
- # Convert the discovered route for this request to appropriate forms and disseminate it to those locations
28
- # where it is necessary for our route coverage and finding vulnerability discovery features to function.
29
- #
30
- # @param route [Contrast::Api::Dtm::RouteCoverage, nil] the route of the current request, as determined from the
31
- # framework
32
- def append_route_coverage route
33
- return unless route
34
-
35
- # For our findings
36
- @route = route
37
-
38
- # REMOVE_DTM_ACTIVITY
39
- #
40
- # For SR findings
41
- @dtm_activity.routes << route
42
-
43
- # For TS routes
44
- @request.route = route
45
- end
46
28
 
47
29
  # Convert the discovered route for this request to appropriate forms and disseminate it to those locations
48
30
  # where it is necessary for our route coverage and finding vulnerability discovery features to function.
49
31
  #
50
- # @param route [Contrast::Api::Dtm::RouteCoverage]
32
+ # @param route [Contrast::Agent::Reporting::RouteCoverage]
51
33
  def append_to_observed_route route
52
34
  return unless route
53
35
 
@@ -55,6 +37,10 @@ module Contrast
55
37
  @observed_route.verb = route.verb
56
38
  @observed_route.url = route.url if route.url
57
39
  @request.observed_route = @observed_route
40
+
41
+ observation = Contrast::Agent::Reporting::RouteDiscoveryObservation.new(route.url, route.verb)
42
+ @discovered_route = Contrast::Agent::Reporting::RouteDiscovery.new(route.route, observation)
43
+ @request.discovered_route = @discovered_route
58
44
  end
59
45
 
60
46
  # @raise [Contrast::SecurityException]
@@ -63,7 +49,6 @@ module Contrast
63
49
  return false unless ::Contrast::PROTECT.enabled?
64
50
  return false if @do_not_track
65
51
 
66
- # REMOVE_DTM_ACTIVITY
67
52
  service_response = Contrast::Agent&.messaging_queue&.send_event_immediately(@activity.request.dtm)
68
53
  return false unless service_response
69
54
 
@@ -117,21 +102,15 @@ module Contrast
117
102
  @response = Contrast::Agent::Response.new(rack_response)
118
103
  return unless @sample_res
119
104
 
120
- # TODO: RUBY-1376 once all rules translated, move this to if/else w/ the enabled
121
- if Contrast::Agent::Reporter.enabled?
122
- Contrast::Agent::Assess::Rule::Response::AutoComplete.new.analyze(@response)
123
- Contrast::Agent::Assess::Rule::Response::CacheControl.new.analyze(@response)
124
- Contrast::Agent::Assess::Rule::Response::ClickJacking.new.analyze(@response)
125
- Contrast::Agent::Assess::Rule::Response::CspHeaderMissing.new.analyze(@response)
126
- Contrast::Agent::Assess::Rule::Response::CspHeaderInsecure.new.analyze(@response)
127
- Contrast::Agent::Assess::Rule::Response::HSTSHeader.new.analyze(@response)
128
- Contrast::Agent::Assess::Rule::Response::ParametersPollution.new.analyze(@response)
129
- Contrast::Agent::Assess::Rule::Response::XContentType.new.analyze(@response)
130
- Contrast::Agent::Assess::Rule::Response::XXssProtection.new.analyze(@response)
131
- else
132
- # REMOVE_DTM_ACTIVITY
133
- dtm_activity.http_response = @response.dtm
134
- end
105
+ Contrast::Agent::Assess::Rule::Response::AutoComplete.new.analyze(@response)
106
+ Contrast::Agent::Assess::Rule::Response::CacheControl.new.analyze(@response)
107
+ Contrast::Agent::Assess::Rule::Response::ClickJacking.new.analyze(@response)
108
+ Contrast::Agent::Assess::Rule::Response::CspHeaderMissing.new.analyze(@response)
109
+ Contrast::Agent::Assess::Rule::Response::CspHeaderInsecure.new.analyze(@response)
110
+ Contrast::Agent::Assess::Rule::Response::HSTSHeader.new.analyze(@response)
111
+ Contrast::Agent::Assess::Rule::Response::ParametersPollution.new.analyze(@response)
112
+ Contrast::Agent::Assess::Rule::Response::XContentType.new.analyze(@response)
113
+ Contrast::Agent::Assess::Rule::Response::XXssProtection.new.analyze(@response)
135
114
  rescue StandardError => e
136
115
  logger.error('Unable to extract information after request', e)
137
116
  end
@@ -4,7 +4,6 @@
4
4
  require 'contrast/components/logger'
5
5
  require 'contrast/components/scope'
6
6
  require 'contrast/agent/reporting/reporter'
7
- require 'contrast/agent/reporting/reporting_utilities/dtm_message'
8
7
  require 'contrast/agent/reporting/masker/masker'
9
8
 
10
9
  module Contrast
@@ -30,13 +29,6 @@ module Contrast
30
29
  return unless (reporter = Contrast::Agent.reporter)
31
30
 
32
31
  reporter.send_event(context.observed_route)
33
- # return unless Contrast::Agent::Reporter.enabled?
34
-
35
- # REMOVE_DTM_ACTIVITY after reporter routes, responses, findings are implemented
36
- #
37
- # This reports routes, findings and traces with response dependent rules.
38
- Contrast::Agent.messaging_queue&.send_event_eventually(context.dtm_activity)
39
-
40
32
  # Mask Sensitive Data
41
33
  Contrast::Agent::Reporting::Masker.mask(context.activity)
42
34
  event = context.activity
@@ -45,24 +45,6 @@ module Contrast
45
45
  end
46
46
  end
47
47
 
48
- # A form of the Rack::Response which we can report to the Service to be sent to TeamServer for processing. B/c
49
- # the response can change, we can't memoize this :(
50
- #
51
- # @return [Contrast::Api::Dtm::HttpResponse]
52
- def dtm
53
- context_response = Contrast::Api::Dtm::HttpResponse.new
54
- context_response.response_code = response_code.to_i
55
- headers&.each_pair do |key, value|
56
- append_pair(context_response.normalized_response_headers, key, value)
57
- end
58
- context_response.response_body_binary = Contrast::Utils::StringUtils.force_utf8(body)
59
-
60
- doc_type = document_type
61
- context_response.document_type = doc_type if doc_type
62
-
63
- context_response
64
- end
65
-
66
48
  # The response code of this response
67
49
  #
68
50
  # @return [Integer]
@@ -21,7 +21,7 @@ module Contrast
21
21
  ''
22
22
  end
23
23
 
24
- def to_hash **_args
24
+ def to_controlled_hash **_args
25
25
  {
26
26
  tags: @tags,
27
27
  timestamp: @timestamp,
@@ -19,7 +19,7 @@ module Contrast
19
19
  @fields['_filler'] = 0
20
20
  end
21
21
 
22
- def to_hash **_args
22
+ def to_controlled_hash **_args
23
23
  super.merge!({ fields: @fields })
24
24
  end
25
25
  end
@@ -50,7 +50,7 @@ module Contrast
50
50
  def initialize
51
51
  super
52
52
  @settings = []
53
- add_config_keys(::Contrast::CONFIG.root, 'root')
53
+ add_config_keys(::Contrast::CONFIG.config, 'root')
54
54
  @settings << ENV.keys.select { |v| v.starts_with?('CONTRAST') }
55
55
  @settings.flatten
56
56
  add_tags
@@ -70,9 +70,9 @@ module Contrast
70
70
  end
71
71
 
72
72
  def add_config_keys config, nested_key
73
- config.to_hash.reject! { |_k, v| REJECTED_VALUES.include?(v) }
73
+ config.to_contrast_hash.reject! { |_k, v| REJECTED_VALUES.include?(v) }
74
74
 
75
- config.to_hash.each do |k, v|
75
+ config.to_contrast_hash.each do |k, v|
76
76
  unless v.cs__class <= Contrast::Config::BaseConfiguration
77
77
  @settings << "#{ nested_key }.#{ k }"
78
78
  next
@@ -3,6 +3,6 @@
3
3
 
4
4
  module Contrast
5
5
  module Agent
6
- VERSION = '6.6.5'
6
+ VERSION = '6.7.0'
7
7
  end
8
8
  end
@@ -29,8 +29,7 @@ module Contrast
29
29
  # types of events include initial settings/ setup on startup and analysis required to complete before handing
30
30
  # execution from our pre-filter operations to the application code (i.e. Protect's input analysis).
31
31
  #
32
- # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of
33
- # Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
32
+ # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of Contrast::Api::Dtm::Message
34
33
  # @return [Contrast::Api::Settings::AgentSettings,nil]
35
34
  def send_event_immediately event
36
35
  if ::Contrast::AGENT.disabled?
@@ -59,7 +58,7 @@ module Contrast
59
58
  # Assess' vulnerability reporting).
60
59
  #
61
60
  # @param event [Contrast::Api::Dtm, Contrast::Api::Dtm::Poll] One of the DTMs valid for the event field of
62
- # Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
61
+ # Contrast::Api::Dtm::Message
63
62
  # @param force [Boolean] if we should always queue this event, even if the service isn't running, in case the
64
63
  # message may be ready before the service has initiated. usually for those events which happen in a separate
65
64
  # thread or which may occur during initialization.
@@ -53,13 +53,13 @@ module Contrast
53
53
  # Log information about the connection being used to communicate between the Agent and SpeedRacer.
54
54
  def log_connection
55
55
  # The socket is set,
56
- if ::Contrast::CONFIG.root.agent.service.socket
56
+ if ::Contrast::CONFIG.agent.service.socket
57
57
  logger.info('Connecting to the Contrast Service using a UnixSocket socket',
58
58
  socket: ::Contrast::CONTRAST_SERVICE.socket_path)
59
59
  return
60
60
  end
61
61
  # The host & port are set,
62
- if ::Contrast::CONFIG.root.agent.service.host && ::Contrast::CONFIG.root.agent.service.port
62
+ if ::Contrast::CONFIG.agent.service.host && ::Contrast::CONFIG.agent.service.port
63
63
  logger.info('Connecting to the Contrast Service using a TCP socket',
64
64
  host: ::Contrast::CONTRAST_SERVICE.host,
65
65
  port: ::Contrast::CONTRAST_SERVICE.port)
@@ -78,11 +78,11 @@ module Contrast
78
78
  #
79
79
  # @return [String]
80
80
  def log_connection_error_msg
81
- if ::Contrast::CONFIG.root.agent.service.host
81
+ if ::Contrast::CONFIG.agent.service.host
82
82
  'Missing a required connection value to the Contrast Service. ' \
83
83
  '`agent.service.port` is not set. ' \
84
84
  'Falling back to default TCP socket port.'
85
- elsif ::Contrast::CONFIG.root.agent.service.port
85
+ elsif ::Contrast::CONFIG.agent.service.port
86
86
  'Missing a required connection value to the Contrast Service. ' \
87
87
  '`agent.service.host` is not set. ' \
88
88
  'Falling back to default TCP socket host.'
@@ -55,8 +55,7 @@ module Contrast
55
55
  # if anything's changed in TeamServer meaning the Agent needs to replace its current settings or there is
56
56
  # Protect analysis information or nil if the current Agent settings do not need updating.
57
57
  #
58
- # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of
59
- # Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
58
+ # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of Contrast::Api::Dtm::Message
60
59
  # @return [Contrast::Api::Settings::AgentSettings,nil]
61
60
  def return_response event
62
61
  send_to_speedracer(event) do |response|
@@ -67,8 +66,7 @@ module Contrast
67
66
  # Send the given Event to SpeedRacer and pass the result to our Contrast::Api::Communication::ResponseProcessor
68
67
  # as there is no immediate action required from sending this Event.
69
68
  #
70
- # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of
71
- # Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
69
+ # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of Contrast::Api::Dtm::Message
72
70
  def process_internally event
73
71
  send_to_speedracer(event) do |response|
74
72
  response_processor.process(response)
@@ -80,8 +78,7 @@ module Contrast
80
78
  # Ensure there is a running SpeedRacer and then send the given Event to it. It is necessary to ensure the
81
79
  # SpeedRacer is running as, if the process has crashed or restarted, we must rebuild our context there.
82
80
  #
83
- # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of
84
- # Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
81
+ # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of Contrast::Api::Dtm::Message
85
82
  # @return [Contrast::Api::Settings::AgentSettings, nil]
86
83
  def send_to_speedracer event
87
84
  ensure_startup!
@@ -131,8 +128,7 @@ module Contrast
131
128
 
132
129
  # Log the startup message we're sending to SpeedRacer
133
130
  #
134
- # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of
135
- # Contrast::Api::Dtm::Message|Contrast::Api::Dtm::Activity
131
+ # @param event [Contrast::Api::Dtm] One of the DTMs valid for the event field of Contrast::Api::Dtm::Message
136
132
  def log_send_event event
137
133
  logger.debug('Immediately sending event.', event_id: event.__id__, event_type: event.cs__class.cs__name)
138
134
  end
@@ -41,12 +41,11 @@ module Contrast
41
41
  #
42
42
  # @param msg [Contrast::Api::Dtm::AgentStartup]
43
43
  def config! msg
44
- msg.version = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.root.server.version)
45
- msg.server_tags = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.root.server.tags)
46
- msg.library_tags = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.root.inventory.tags)
47
- msg.environment = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.root.server.environment)
48
- msg.application_tags =
49
- Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.root.application.tags)
44
+ msg.version = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.server.version)
45
+ msg.server_tags = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.server.tags)
46
+ msg.library_tags = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.inventory.tags)
47
+ msg.environment = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.server.environment)
48
+ msg.application_tags = Contrast::Utils::StringUtils.protobuf_format(::Contrast::CONFIG.application.tags)
50
49
  end
51
50
  end
52
51
  end
@@ -31,7 +31,8 @@ module Contrast
31
31
  {
32
32
  modes_by_id: translated_protection_mode_by_id,
33
33
  exclusion_matchers: translated_exclusions,
34
- disabled_assess_rules: disabled_assess_rules
34
+ disabled_assess_rules: disabled_assess_rules,
35
+ session_id: session_id
35
36
  }
36
37
  end
37
38
  end