contrast-agent 3.14.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +18 -15
  3. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +1 -0
  4. data/ext/cs__assess_string/cs__assess_string.c +24 -25
  5. data/ext/cs__assess_string/cs__assess_string.h +3 -1
  6. data/ext/cs__common/cs__common.c +4 -2
  7. data/ext/cs__common/cs__common.h +1 -1
  8. data/lib/contrast.rb +1 -1
  9. data/lib/contrast/agent/assess.rb +1 -0
  10. data/lib/contrast/agent/assess/contrast_event.rb +4 -12
  11. data/lib/contrast/agent/assess/finalizers/freeze.rb +3 -1
  12. data/lib/contrast/agent/assess/finalizers/hash.rb +45 -1
  13. data/lib/contrast/agent/assess/policy/patcher.rb +1 -1
  14. data/lib/contrast/agent/assess/policy/policy.rb +0 -2
  15. data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -1
  16. data/lib/contrast/agent/assess/policy/preshift.rb +7 -11
  17. data/lib/contrast/agent/assess/policy/propagation_method.rb +50 -33
  18. data/lib/contrast/agent/assess/policy/propagator/append.rb +8 -5
  19. data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
  20. data/lib/contrast/agent/assess/policy/propagator/center.rb +9 -5
  21. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +5 -3
  22. data/lib/contrast/agent/assess/policy/propagator/insert.rb +6 -3
  23. data/lib/contrast/agent/assess/policy/propagator/keep.rb +4 -1
  24. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +6 -6
  25. data/lib/contrast/agent/assess/policy/propagator/next.rb +7 -5
  26. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +8 -5
  27. data/lib/contrast/agent/assess/policy/propagator/remove.rb +8 -4
  28. data/lib/contrast/agent/assess/policy/propagator/replace.rb +5 -2
  29. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +7 -5
  30. data/lib/contrast/agent/assess/policy/propagator/select.rb +15 -7
  31. data/lib/contrast/agent/assess/policy/propagator/splat.rb +14 -8
  32. data/lib/contrast/agent/assess/policy/propagator/split.rb +14 -8
  33. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +30 -21
  34. data/lib/contrast/agent/assess/policy/propagator/trim.rb +11 -5
  35. data/lib/contrast/agent/assess/policy/source_method.rb +85 -58
  36. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +16 -11
  37. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
  38. data/lib/contrast/agent/assess/policy/trigger_method.rb +38 -15
  39. data/lib/contrast/agent/assess/policy/trigger_node.rb +14 -13
  40. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +2 -1
  41. data/lib/contrast/agent/assess/properties.rb +2 -0
  42. data/lib/contrast/agent/assess/property/updated.rb +136 -0
  43. data/lib/contrast/agent/assess/tracker.rb +66 -0
  44. data/lib/contrast/agent/class_reopener.rb +7 -5
  45. data/lib/contrast/agent/middleware.rb +0 -1
  46. data/lib/contrast/agent/patching/policy/patcher.rb +13 -22
  47. data/lib/contrast/agent/patching/policy/policy.rb +1 -4
  48. data/lib/contrast/agent/response.rb +17 -6
  49. data/lib/contrast/agent/rewriter.rb +1 -3
  50. data/lib/contrast/agent/version.rb +1 -1
  51. data/lib/contrast/api/communication/messaging_queue.rb +1 -4
  52. data/lib/contrast/api/decorators/application_update.rb +2 -4
  53. data/lib/contrast/api/decorators/trace_event.rb +5 -5
  54. data/lib/contrast/components/app_context.rb +11 -9
  55. data/lib/contrast/components/config.rb +3 -13
  56. data/lib/contrast/components/contrast_service.rb +2 -2
  57. data/lib/contrast/config/application_configuration.rb +5 -2
  58. data/lib/contrast/config/service_configuration.rb +8 -2
  59. data/lib/contrast/configuration.rb +88 -47
  60. data/lib/contrast/extension/assess.rb +0 -2
  61. data/lib/contrast/extension/assess/array.rb +8 -5
  62. data/lib/contrast/extension/assess/erb.rb +6 -3
  63. data/lib/contrast/extension/assess/fiber.rb +9 -9
  64. data/lib/contrast/extension/assess/hash.rb +2 -3
  65. data/lib/contrast/extension/assess/kernel.rb +12 -5
  66. data/lib/contrast/extension/assess/marshal.rb +3 -2
  67. data/lib/contrast/extension/assess/regexp.rb +5 -4
  68. data/lib/contrast/extension/assess/string.rb +8 -10
  69. data/lib/contrast/framework/rack/patch/session_cookie.rb +12 -18
  70. data/lib/contrast/framework/rails/patch/assess_configuration.rb +4 -10
  71. data/lib/contrast/framework/rails/support.rb +2 -0
  72. data/lib/contrast/logger/application.rb +11 -3
  73. data/lib/contrast/utils/assess/tracking_util.rb +48 -3
  74. data/lib/contrast/utils/duck_utils.rb +0 -10
  75. data/lib/contrast/utils/env_configuration_item.rb +2 -1
  76. data/lib/contrast/utils/invalid_configuration_util.rb +21 -19
  77. data/lib/contrast/utils/string_utils.rb +10 -5
  78. data/resources/assess/policy.json +0 -10
  79. data/ruby-agent.gemspec +16 -15
  80. data/service_executables/VERSION +1 -1
  81. data/service_executables/linux/contrast-service +0 -0
  82. data/service_executables/mac/contrast-service +0 -0
  83. metadata +42 -21
  84. data/lib/contrast/agent/assess/finalizers/finalize.rb +0 -21
  85. data/lib/contrast/extension/assess/assess_extension.rb +0 -145
  86. data/lib/contrast/utils/freeze_util.rb +0 -32
@@ -7,21 +7,24 @@ module ERBPropagator
7
7
  def result_tagger patcher, preshift, ret, _block
8
8
  return unless preshift.args.length >= 1
9
9
 
10
+ properties = Contrast::Agent::Assess::Tracker.properties(ret)
11
+ return unless properties
12
+
10
13
  used_binding = preshift.args[0]
11
14
  binding_variable_set = used_binding.local_variables
12
15
 
13
16
  erb_pre_result = preshift.object.src
14
17
  binding_variable_set.each do |bound_var_symbol|
15
18
  bound_variable_value = used_binding.local_variable_get(bound_var_symbol)
16
- next unless bound_variable_value.cs__respond_to?(:cs__tracked?) && bound_variable_value.cs__tracked?
19
+ next unless Contrast::Agent::Assess::Tracker.tracked?(bound_variable_value)
17
20
  next unless erb_pre_result.include?(bound_var_symbol.to_s)
18
21
 
19
22
  start_index = ret.index(bound_variable_value)
20
23
  next if start_index.nil?
21
24
 
22
- ret.cs__copy_from(bound_variable_value, start_index)
25
+ properties.copy_from(bound_variable_value, ret, start_index)
23
26
  end
24
- ret.cs__properties.build_event(
27
+ properties.build_event(
25
28
  patcher,
26
29
  ret,
27
30
  preshift.object,
@@ -54,7 +54,6 @@ module Contrast
54
54
  class << self
55
55
  def track_rb_fiber_yield fiber, _method, results
56
56
  return unless ASSESS.enabled?
57
- return unless Contrast::Utils::DuckUtils.trackable?(fiber)
58
57
 
59
58
  # results will be nil if StopIteration was raised,
60
59
  # otherwise an Array of the yielded arguments
@@ -62,11 +61,11 @@ module Contrast
62
61
 
63
62
  with_contrast_scope do
64
63
  results.each do |result|
65
- next unless Contrast::Utils::DuckUtils.trackable?(result)
66
- next if result.cs__frozen?
64
+ result_properties = Contrast::Agent::Assess::Tracker.properties(result)
65
+ next unless result_properties
67
66
 
68
- fiber.cs__splat_tags(result)
69
- result.cs__properties.build_event(
67
+ result_properties.splat_from(fiber, result)
68
+ result_properties.build_event(
70
69
  FIBER_YIELD_NODE,
71
70
  result,
72
71
  fiber,
@@ -80,13 +79,14 @@ module Contrast
80
79
 
81
80
  def track_rb_fiber_new fiber, _enum, _enum_method, underlying, _underlying_method
82
81
  return unless ASSESS.enabled?
83
- return unless Contrast::Utils::DuckUtils.trackable?(fiber)
84
- return unless Contrast::Utils::DuckUtils.trackable?(underlying)
85
82
  return unless underlying.is_a?(String) && !underlying.empty?
86
83
 
87
84
  with_contrast_scope do
88
- underlying.cs__splat_tags(fiber)
89
- fiber.cs__properties.build_event(
85
+ properties = Contrast::Agent::Assess::Tracker.properties(fiber)
86
+ return unless properties
87
+
88
+ properties.splat_from(underlying, fiber)
89
+ properties.build_event(
90
90
  FIBER_NEW_NODE,
91
91
  fiber,
92
92
  underlying,
@@ -15,10 +15,9 @@ module Contrast
15
15
  class << self
16
16
  def cs__duplicate_and_freeze object
17
17
  return object unless object.is_a?(String) && !object.cs__frozen?
18
- return object unless object.cs__tracked?
18
+ return object unless Contrast::Agent::Assess::Tracker.tracked?(object)
19
19
 
20
- ret = object.dup
21
- object.cs__transfer_properties(ret)
20
+ ret = Contrast::Agent::Assess::Tracker.duplicate(object)
22
21
  ret.cs__freeze
23
22
  rescue StandardError
24
23
  # we'll rescue this error, but we can't log it here as that will
@@ -39,12 +39,15 @@ module Contrast
39
39
  # oh, and there's also %<name>type and %{name}... b/c of course there is
40
40
  # -HM
41
41
  def sprintf_tagger patcher, preshift, ret, _block
42
+ properties = Contrast::Agent::Assess::Tracker.properties(ret)
43
+ return unless properties
44
+
42
45
  format_string = preshift.args[0]
43
46
  args = preshift.args[1]
44
47
 
45
48
  track_sprintf(ret, format_string, args)
46
49
 
47
- ret.cs__properties.build_event(
50
+ properties.build_event(
48
51
  patcher,
49
52
  ret,
50
53
  preshift.object,
@@ -85,12 +88,16 @@ module Contrast
85
88
  private
86
89
 
87
90
  def handle_sprintf_value value, result
88
- return unless Contrast::Utils::DuckUtils.trackable?(value) && value.cs__tracked?
91
+ properties = Contrast::Agent::Assess::Tracker.properties(result)
92
+ return unless properties
93
+
94
+ value_properties = Contrast::Agent::Assess::Tracker.properties(value)
95
+ return unless value_properties
89
96
 
90
- value.cs__properties.events.each do |event|
91
- result.cs__properties.events << event
97
+ value_properties.events.each do |event|
98
+ properties.events << event
92
99
  end
93
- value.cs__splat_tags(result)
100
+ properties.splat_from(value, result)
94
101
  end
95
102
 
96
103
  def handle_sprintf_array args, result
@@ -22,7 +22,7 @@ module Contrast
22
22
 
23
23
  # Since we know this is the source of the trigger, we can do some
24
24
  # optimization here and return when it is not tracked
25
- return unless Contrast::Utils::Assess::TrackingUtil.tracked?(source)
25
+ return unless Contrast::Agent::Assess::Tracker.tracked?(source)
26
26
 
27
27
  # source might not be all the args passed in, but it is the one we care
28
28
  # about. we could pass in all the args in the last param here if it
@@ -34,7 +34,8 @@ module Contrast
34
34
  self,
35
35
  ret,
36
36
  source)
37
- ret.cs__copy_from(source) if ret.cs__respond_to?(:cs__copy_from)
37
+ properties = Contrast::Agent::Assess::Tracker.properties(ret)
38
+ properties.copy_from(source, ret)
38
39
  rescue StandardError => e
39
40
  logger.error('Unable to determine if a trigger occurred in Marshal.load', e)
40
41
  end
@@ -47,8 +47,6 @@ module Contrast
47
47
  return if scope_for_current_ec.instance_variable_get(:@contrast_scope) > 1
48
48
 
49
49
  target = info_hash[:back_ref]
50
- return unless Contrast::Utils::DuckUtils.trackable?(target)
51
-
52
50
  with_contrast_scope do
53
51
  result = info_hash[:result]
54
52
  return unless result
@@ -56,8 +54,11 @@ module Contrast
56
54
  string = info_hash[:string]
57
55
  return unless string
58
56
 
59
- string.cs__splat_tags(target)
60
- target.cs__properties.build_event(
57
+ properties = Contrast::Agent::Assess::Tracker.properties(target)
58
+ return unless properties
59
+
60
+ properties.splat_from(string, target)
61
+ properties.build_event(
61
62
  REGEXP_EQUAL_SQUIGGLE_NODE,
62
63
  target,
63
64
  self,
@@ -3,13 +3,6 @@
3
3
 
4
4
  require 'contrast/agent/assess/policy/propagation_node'
5
5
  require 'contrast/components/interface'
6
- require 'contrast/extension/assess/assess_extension'
7
-
8
- # This patch installs our extension as early as possible. The alternative is to
9
- # litter our code with Contrast::Utils::DuckUtils.trackable? checks.
10
- class String
11
- include Contrast::Extension::Assess::AssessExtension
12
- end
13
6
 
14
7
  module Contrast
15
8
  module Extension
@@ -40,16 +33,21 @@ module Contrast
40
33
  def track_interpolation inputs, result
41
34
  return unless AGENT.interpolation_enabled?
42
35
  return if in_contrast_scope?
43
- return unless inputs.any?(&:cs__tracked?)
36
+ return unless inputs.any? { |input| Contrast::Agent::Assess::Tracker.tracked?(input) }
44
37
 
45
38
  with_contrast_scope do
39
+ properties = Contrast::Agent::Assess::Tracker.properties(result)
40
+ return unless properties
41
+
46
42
  offset = 0
47
43
  inputs.each do |input|
48
- result.cs__copy_from(input, offset)
44
+ properties.copy_from(input, result, offset)
49
45
  offset += input.length
50
46
  end
51
- result.cs__properties.build_event(INTERPOLATION_NODE, result, inputs, result, inputs)
47
+ properties.build_event(INTERPOLATION_NODE, result, inputs, result, inputs)
52
48
  end
49
+ rescue StandardError => e
50
+ logger.error('Unable to track interpolation', e)
53
51
  end
54
52
 
55
53
  def instrument_string
@@ -67,12 +67,10 @@ module Contrast
67
67
  options,
68
68
  safe_default: false)
69
69
 
70
- with_contrast_scope do
71
- cs__report_finding(
72
- CS__SECURE_RULE_NAME,
73
- options,
74
- caller_locations(10, 9)[0])
75
- end
70
+ cs__report_finding(
71
+ CS__SECURE_RULE_NAME,
72
+ options,
73
+ caller_locations(10, 9)[0])
76
74
  rescue StandardError => e
77
75
  begin
78
76
  logger.error('Unable to track call to secure session', e)
@@ -88,12 +86,10 @@ module Contrast
88
86
  safe_default: false,
89
87
  comparison_type: :greater_than)
90
88
 
91
- with_contrast_scope do
92
- cs__report_finding(
93
- CS__SESSION_TIMEOUT_NAME,
94
- options,
95
- caller_locations(10, 9)[0])
96
- end
89
+ cs__report_finding(
90
+ CS__SESSION_TIMEOUT_NAME,
91
+ options,
92
+ caller_locations(10, 9)[0])
97
93
  rescue StandardError => e
98
94
  begin
99
95
  logger.error('Unable to track call to set session timeout', e)
@@ -105,12 +101,10 @@ module Contrast
105
101
  def apply_httponly options
106
102
  return unless vulnerable_setting?(:httponly, true, options)
107
103
 
108
- with_contrast_scope do
109
- cs__report_finding(
110
- CS__HTTPONLY_NAME,
111
- options,
112
- caller_locations(10, 9)[0])
113
- end
104
+ cs__report_finding(
105
+ CS__HTTPONLY_NAME,
106
+ options,
107
+ caller_locations(10, 9)[0])
114
108
  rescue StandardError => e
115
109
  begin
116
110
  logger.error('Unable to track call to httponly', e)
@@ -12,7 +12,7 @@ module Contrast
12
12
  module AssessConfiguration
13
13
  include Contrast::Components::Interface
14
14
 
15
- access_component :agent, :analysis, :logging, :scope
15
+ access_component :agent, :analysis, :logging
16
16
 
17
17
  CS__SESSION_TIMEOUT_NAME = 'session-timeout'
18
18
  SAFE_SESSION_TIMEOUT = (30 * 60 * 1000)
@@ -52,9 +52,7 @@ module Contrast
52
52
  return unless vulnerable_setting?(:expire_after, SAFE_SESSION_TIMEOUT, args, comparison_type: :greater_than, safe_default: false)
53
53
 
54
54
  rails_session_settings = args[1]
55
- with_contrast_scope do
56
- cs__report_finding(CS__SESSION_TIMEOUT_NAME, rails_session_settings, caller_locations(6, 5)[0])
57
- end
55
+ cs__report_finding(CS__SESSION_TIMEOUT_NAME, rails_session_settings, caller_locations(3, 2)[0])
58
56
  rescue StandardError => e
59
57
  begin
60
58
  logger.error('Unable to track call to set session timeout', e)
@@ -68,9 +66,7 @@ module Contrast
68
66
  return unless vulnerable_setting?(:secure, true, args)
69
67
 
70
68
  rails_session_settings = args[1]
71
- with_contrast_scope do
72
- cs__report_finding(CS__SECURE_RULE_NAME, rails_session_settings, caller_locations(6, 5)[0])
73
- end
69
+ cs__report_finding(CS__SECURE_RULE_NAME, rails_session_settings, caller_locations(3, 2)[0])
74
70
  rescue StandardError => e
75
71
  begin
76
72
  logger.error('Unable to track call to disable secure cookies', e)
@@ -84,9 +80,7 @@ module Contrast
84
80
  return unless vulnerable_setting?(:httponly, true, args)
85
81
 
86
82
  rails_session_settings = args[1]
87
- with_contrast_scope do
88
- cs__report_finding(CS__HTTPONLY_RULE_NAME, rails_session_settings, caller_locations(6, 5)[0])
89
- end
83
+ cs__report_finding(CS__HTTPONLY_RULE_NAME, rails_session_settings, caller_locations(3, 2)[0])
90
84
  rescue StandardError => e
91
85
  begin
92
86
  logger.error('Unable to track call to disable httponly in session cookie', e)
@@ -118,6 +118,8 @@ module Contrast
118
118
 
119
119
  # Rails engine routes need to be detected by inspecting Engine class route set
120
120
  def find_all_routes app, route_list
121
+ return route_list unless app.cs__respond_to?(:routes) && app.routes.cs__respond_to?(:routes)
122
+
121
123
  app.routes.routes.each do |route|
122
124
  if route.cs__respond_to?(:app) && route.app.cs__class == ActionDispatch::Routing::RouteSet::Dispatcher
123
125
  route_list << Contrast::Api::Dtm::RouteCoverage.from_action_dispatch_journey(route)
@@ -33,9 +33,17 @@ module Contrast
33
33
  def application_configuration
34
34
  return unless info?
35
35
 
36
- loggable = CONFIG.raw.send(:load_config)
37
- loggable.delete('api')
38
- info('Current configuration', configuration: JSON.pretty_generate(loggable))
36
+ loggable = CONFIG.raw.loggable
37
+ info('Current configuration', configuration: loggable)
38
+ env_keys = ENV.keys.select { |env_key| env_key&.to_s&.start_with?(Contrast::Components::Config::CONTRAST_ENV_MARKER) }
39
+ env_items = env_keys.map { |env_key| Contrast::Utils::EnvConfigurationItem.new(env_key, nil) }
40
+ env_translations = env_items.each_with_object({}) do |conversion, hash|
41
+ hash[conversion.key] = conversion.dot_path_array.join('.')
42
+ end
43
+ info('Set by environment', overrides: env_translations)
44
+ rescue StandardError => e
45
+ puts e
46
+ sleep(5)
39
47
  end
40
48
 
41
49
  def application_libraries
@@ -1,7 +1,9 @@
1
1
  # Copyright (c) 2020 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/assess/tracker'
4
5
  require 'contrast/components/interface'
6
+ require 'contrast/utils/duck_utils'
5
7
 
6
8
  module Contrast
7
9
  module Utils
@@ -23,6 +25,16 @@ module Contrast
23
25
  _tracked?(obj, 0)
24
26
  end
25
27
 
28
+ # Public interface to our tracking check, isolating the internals
29
+ # required for recursion.
30
+ #
31
+ # @param obj [Object] the thing to check if tracked
32
+ # @return [Boolean] if the obj, or something in it if a collection, is
33
+ # tracked.
34
+ def trackable? obj
35
+ _trackable?(obj, 0)
36
+ end
37
+
26
38
  private
27
39
 
28
40
  # Sometimes things are nested inside of each other, such as an Array
@@ -49,10 +61,8 @@ module Contrast
49
61
  obj.any? do |ele|
50
62
  _tracked?(ele, idx) unless obj == ele
51
63
  end
52
- elsif Contrast::Utils::DuckUtils.quacks_to?(obj, :cs__tracked?)
53
- obj.cs__tracked?
54
64
  else
55
- false
65
+ Contrast::Agent::Assess::Tracker.tracked?(obj)
56
66
  end
57
67
  rescue StandardError => e
58
68
  # This is used to ask if a ton of objects are tracked. They may not
@@ -61,6 +71,41 @@ module Contrast
61
71
  logger.warn('Failed to determine tracking', e, module: obj.cs__class)
62
72
  false
63
73
  end
74
+
75
+ # Sometimes things are nested inside of each other, such as an Array
76
+ # holding a Hash, holding that Array. In those cases, rather than
77
+ # entering an infinite loop, we'll break out.
78
+ # Right now, that level of nesting has been arbitrarily set to 10.
79
+ #
80
+ # @param obj [Object] the thing to check if trackable
81
+ # @param idx [Integer] the number of levels nested we've gone
82
+ # @return [Boolean] if the obj, or something in it if a collection, is
83
+ # trackable.
84
+ def _trackable? obj, idx
85
+ return false if obj.nil?
86
+ return false if idx > 10
87
+
88
+ idx += 1
89
+ if Contrast::Utils::DuckUtils.iterable_hash?(obj)
90
+ obj.each_pair do |k, v|
91
+ return true if _trackable?(k, idx)
92
+ return true if _trackable?(v, idx)
93
+ end
94
+ false
95
+ elsif Contrast::Utils::DuckUtils.iterable_enumerable?(obj)
96
+ obj.any? do |ele|
97
+ _trackable?(ele, idx) unless obj == ele
98
+ end
99
+ else
100
+ Contrast::Agent::Assess::Tracker.trackable?(obj)
101
+ end
102
+ rescue StandardError => e
103
+ # This is used to ask if a ton of objects are tracked. They may not
104
+ # all be iterable. Bad things could happen in some cases, like when
105
+ # checking a closed statement for SQL injection trigger events
106
+ logger.warn('Failed to determine trackable', e, module: obj.cs__class)
107
+ false
108
+ end
64
109
  end
65
110
  end
66
111
  end
@@ -62,16 +62,6 @@ module Contrast
62
62
  # otherwise, don't risk it
63
63
  false
64
64
  end
65
-
66
- # This method will return true if the object being checked has been patched
67
- # to have the cs__properties field. We check the cs__tracked? method since it
68
- # is side effect free (ie doesn't cause the properties object to be created).
69
- def trackable? object
70
- return true if object.cs__respond_to?(:cs__tracked?)
71
- return false unless object.is_a?(Delegator)
72
-
73
- object.cs__delegator_respond_to?(:cs__tracked?)
74
- end
75
65
  end
76
66
  end
77
67
  end
@@ -10,10 +10,11 @@ module Contrast
10
10
  END_UNDERSCORE = /(_+)$/.cs__freeze
11
11
  REPEATING_UNDERSCORE = /_{3,}/.cs__freeze
12
12
 
13
- attr_reader :value, :dot_path_array
13
+ attr_reader :value, :dot_path_array, :key
14
14
 
15
15
  def initialize key, value
16
16
  key = EnvConfigurationItem.resolve_corrected_path(key)
17
+ @key = key
17
18
  @dot_path_array = key.downcase.split(Contrast::Utils::ObjectShare::DOUBLE_UNDERSCORE)
18
19
  @value = value
19
20
 
@@ -9,7 +9,7 @@ module Contrast
9
9
  # customer applications, as determined by Configuration Rules at runtime.
10
10
  module InvalidConfigurationUtil
11
11
  include Contrast::Components::Interface
12
- access_component :analysis, :app_context, :logging
12
+ access_component :analysis, :app_context, :logging, :scope
13
13
 
14
14
  CS__PATH = 'path'
15
15
  CS__SESSION_ID = 'sessionId'
@@ -23,28 +23,30 @@ module Contrast
23
23
  # @param call_location [Thread::Backtrace::Location] the location where
24
24
  # the bad configuration was set
25
25
  def cs__report_finding rule_id, user_provided_options, call_location
26
- finding = Contrast::Api::Dtm::Finding.new
27
- finding.rule_id = rule_id
28
- path = call_location.path
29
- # just get the file name, not the full path
30
- path = path.split(Contrast::Utils::ObjectShare::SLASH).last
31
- session_id = user_provided_options[:key].to_s if user_provided_options
26
+ with_contrast_scope do
27
+ finding = Contrast::Api::Dtm::Finding.new
28
+ finding.rule_id = rule_id
29
+ path = call_location.path
30
+ # just get the file name, not the full path
31
+ path = path.split(Contrast::Utils::ObjectShare::SLASH).last
32
+ session_id = user_provided_options[:key].to_s if user_provided_options
32
33
 
33
- finding.version = Contrast::Agent::Assess::Policy::TriggerMethod::CURRENT_FINDING_VERSION
34
- finding.properties[CS__SESSION_ID] = Contrast::Utils::StringUtils.force_utf8(session_id)
35
- finding.properties[CS__PATH] = Contrast::Utils::StringUtils.force_utf8(path)
36
- file_path = call_location.absolute_path
37
- snippet = file_snippet(file_path, call_location)
38
- finding.properties[CS__SNIPPET] = Contrast::Utils::StringUtils.force_utf8(snippet)
34
+ finding.version = Contrast::Agent::Assess::Policy::TriggerMethod::CURRENT_FINDING_VERSION
35
+ finding.properties[CS__SESSION_ID] = Contrast::Utils::StringUtils.force_utf8(session_id)
36
+ finding.properties[CS__PATH] = Contrast::Utils::StringUtils.force_utf8(path)
37
+ file_path = call_location.absolute_path
38
+ snippet = file_snippet(file_path, call_location)
39
+ finding.properties[CS__SNIPPET] = Contrast::Utils::StringUtils.force_utf8(snippet)
39
40
 
40
- hash = Contrast::Utils::HashDigest.generate_config_hash(finding)
41
- finding.hash_code = Contrast::Utils::StringUtils.force_utf8(hash)
42
- finding.preflight = Contrast::Utils::PreflightUtil.create_preflight(finding)
41
+ hash = Contrast::Utils::HashDigest.generate_config_hash(finding)
42
+ finding.hash_code = Contrast::Utils::StringUtils.force_utf8(hash)
43
+ finding.preflight = Contrast::Utils::PreflightUtil.create_preflight(finding)
43
44
 
44
- activity = Contrast::Api::Dtm::Activity.new
45
- activity.findings << finding
45
+ activity = Contrast::Api::Dtm::Activity.new
46
+ activity.findings << finding
46
47
 
47
- Contrast::Agent.messaging_queue.send_event_eventually(activity)
48
+ Contrast::Agent.messaging_queue.send_event_eventually(activity)
49
+ end
48
50
  rescue StandardError => e
49
51
  logger.error('Unable to build a finding', e, rule: rule_id)
50
52
  end