contrast-agent 6.6.5 → 6.7.0

Sign up to get free protection for your applications and to get access to all the features.
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