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
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ module Contrast
5
+ module Components
6
+ module Ruby
7
+ # A wrapper build around the Common Agent Configuration project to allow
8
+ # for access of the values contained in its
9
+ # parent_configuration_spec.yaml.
10
+ # Those in this section pertain to the specific settings that apply to Ruby
11
+ class Interface
12
+ include Contrast::Components::ComponentBase
13
+
14
+ DISABLED_RAKE_TASK_LIST = %w[
15
+ about assets:clean assets:clobber assets:environment
16
+ assets:precompile assets:precompile:all db:create db:drop db:fixtures:load db:migrate
17
+ db:migrate:status db:rollback db:schema:cache:clear db:schema:cache:dump db:schema:dump
18
+ db:schema:load db:seed db:setup db:structure:dump db:version doc:app graphql:install graphql:object
19
+ log:clear middleware notes notes:custom rails:template rails:update routes secret spec spec:features
20
+ spec:requests spec:controllers spec:helpers spec:models spec:views spec:routing spec:rcov stats
21
+ test test:all test:all:db test:recent test:single test:uncommitted time:zones:all tmp:clear
22
+ tmp:create webpacker:compile contrast:service:start contrast:service:status contrast:service:stop
23
+ ].cs__freeze
24
+
25
+ DEFAULT_UNINSTRUMENTED_NAMESPACES = %w[FactoryGirl FactoryBot].cs__freeze
26
+
27
+ attr_writer :disabled_agent_rake_tasks, :exceptions, :propagate_yield, :require_scan,
28
+ :non_request_tracking, :uninstrument_namespace
29
+
30
+ def initialize hsh = {}
31
+ return unless hsh
32
+
33
+ @disabled_agent_rake_tasks = hsh[:disabled_agent_rake_tasks]
34
+ @exceptions = Contrast::Config::ExceptionConfiguration.new(hsh[:exceptions])
35
+ @propagate_yield = hsh[:propagate_yield]
36
+ @require_scan = hsh[:require_scan]
37
+ @non_request_tracking = hsh[:non_request_tracking]
38
+ @uninstrument_namespace = hsh[:uninstrument_namespace]
39
+ end
40
+
41
+ # These commands being detected will result the agent disabling instrumentation, generally any command
42
+ # that doesn't result in the application listening on a port can be added here, this normally includes tasks
43
+ # that are ran pre-startup(like migrations) or to show information about the application(such as routes)
44
+ # @return [Array, DISABLED_RAKE_TASK_LIST]
45
+ def disabled_agent_rake_tasks
46
+ @disabled_agent_rake_tasks.nil? ? DISABLED_RAKE_TASK_LIST : @disabled_agent_rake_tasks
47
+ end
48
+
49
+ # rubocop:disable Naming/MemoizedInstanceVariableName
50
+ # @return [Contrast::Config::ExceptionConfiguration]
51
+ def exceptions
52
+ @exceptions ||= Contrast::Config::ExceptionConfiguration.new
53
+ end
54
+ # rubocop:enable Naming/MemoizedInstanceVariableName
55
+
56
+ # controls whether or not we patch the rb_yield block to track split propagation
57
+ # @return [Boolean, Contrast::Utils::ObjectShare::TRUE]
58
+ def propagate_yield
59
+ @propagate_yield.nil? ? Contrast::Utils::ObjectShare::TRUE : @propagate_yield
60
+ end
61
+
62
+ # control whether or not we run file scanning rules on require
63
+ # @return [Boolean, Contrast::Utils::ObjectShare::TRUE]
64
+ def require_scan
65
+ @require_scan.nil? ? Contrast::Utils::ObjectShare::TRUE : @require_scan
66
+ end
67
+
68
+ # controls tracking outside of request
69
+ # @return [Boolean, Contrast::Utils::ObjectShare::FALSE]
70
+ def non_request_tracking
71
+ @non_request_tracking.nil? ? Contrast::Utils::ObjectShare::FALSE : @non_request_tracking
72
+ end
73
+
74
+ # @return [Array, DEFAULT_UNINSTRUMENTED_NAMESPACES]
75
+ def uninstrument_namespace
76
+ @uninstrument_namespace.nil? ? DEFAULT_UNINSTRUMENTED_NAMESPACES : @uninstrument_namespace
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -24,7 +24,7 @@ module Contrast
24
24
 
25
25
  def sampling_control
26
26
  @_sampling_control ||= begin
27
- config_settings = ::Contrast::CONFIG.root.assess&.sampling
27
+ config_settings = ::Contrast::CONFIG.assess&.sampling
28
28
  settings = ::Contrast::SETTINGS&.assess_state&.sampling_settings
29
29
  {
30
30
  enabled: enabled?(config_settings, settings),
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ module Contrast
5
+ module Components
6
+ module SecurityLogger
7
+ # Here we will read and store the setting for the CEF Logging functionality
8
+ class Interface
9
+ # @return [String, nil]
10
+ attr_accessor :path
11
+ # @return [String, nil]
12
+ attr_accessor :level
13
+
14
+ def initialize hsh = {}
15
+ return unless hsh
16
+
17
+ @path = hsh[:path]
18
+ @level = hsh[:level]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/components/base'
5
+ require 'contrast/components/logger'
6
+
7
+ module Contrast
8
+ module Components
9
+ module Service
10
+ # A wrapper build around the Common Agent Configuration project to allow
11
+ # for access of the values contained in its
12
+ # parent_configuration_spec.yaml.
13
+ # Those in this section pertain to the communication between the Agent & the Service
14
+ class Interface
15
+ include Contrast::Components::ComponentBase
16
+
17
+ # We don't set these b/c we've been asked to handle the default values of these settings differently, logging
18
+ # when we have to use them.
19
+ DEFAULT_HOST = '127.0.0.1' # rubocop:disable Style/IpAddresses
20
+ DEFAULT_PORT = '30555'
21
+
22
+ attr_writer :logger, :bypass
23
+ # @return [String, nil]
24
+ attr_accessor :socket
25
+ # @return [String, nil]
26
+ attr_accessor :port
27
+ # @return [String, nil]
28
+ attr_accessor :host
29
+ # @return [Boolean, nil]
30
+ attr_accessor :enable
31
+
32
+ def initialize hsh = {}
33
+ return unless hsh
34
+
35
+ @enable = hsh[:enable]
36
+ @host = hsh[:host]
37
+ @port = hsh[:port]
38
+ @socket = hsh[:socket]
39
+ @logger = Contrast::Components::Logger::Interface.new(hsh[:logger])
40
+ @bypass = hsh[:bypass]
41
+ end
42
+
43
+ # @return [Contrast::Components::Logger::Interface]
44
+ def logger
45
+ @logger ||= Contrast::Components::Logger::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
46
+ end
47
+
48
+ # @return [Boolean, false]
49
+ def bypass
50
+ @bypass.nil? ? false : @bypass
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -2,7 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/api/settings.pb'
5
+ require 'contrast/agent/excluder'
5
6
  require 'contrast/agent/reporting/settings/sensitive_data_masking'
7
+ require 'contrast/components/config'
6
8
 
7
9
  module Contrast
8
10
  module Components
@@ -24,7 +26,7 @@ module Contrast
24
26
  SENSITIVE_DATA_MASKING_BASE = Contrast::Agent::Reporting::Settings::SensitiveDataMasking.new
25
27
 
26
28
  # This is a class.
27
- class Interface
29
+ class Interface # rubocop:disable Metrics/ClassLength
28
30
  extend Contrast::Components::Config
29
31
 
30
32
  # tainted_columns are database columns that receive unsanitized input.
@@ -90,6 +92,8 @@ module Contrast
90
92
  attr_reader :last_app_update_ms
91
93
  # @return [Integer] the time, in ms, that server settings last changed
92
94
  attr_reader :last_server_update_ms
95
+ # @return [Contrast::Agent::Excluder] a wrapper around the exclusion rules for the application
96
+ attr_reader :excluder
93
97
 
94
98
  def initialize
95
99
  reset_state
@@ -120,7 +124,11 @@ module Contrast
120
124
  new_vals = settings_response.application_state_translation
121
125
  @application_state.modes_by_id = new_vals[:modes_by_id]
122
126
  @application_state.exclusion_matchers = new_vals[:exclusion_matchers]
127
+ @excluder = Contrast::Agent::Excluder.new(@application_state.exclusion_matchers)
123
128
  @assess_state.disabled_assess_rules = new_vals[:disabled_assess_rules]
129
+ if settings_response.session_id && !settings_response.session_id.blank?
130
+ @assess_state.session_id = settings_response.session_id
131
+ end
124
132
  @last_app_update_ms = Contrast::Utils::Timer.now_ms
125
133
  end
126
134
  @last_app_update_ms = Contrast::Utils::Timer.now_ms
@@ -133,6 +141,7 @@ module Contrast
133
141
  @application_state = APPLICATION_STATE_BASE.dup
134
142
  @tainted_columns = {}
135
143
  @sensitive_data_masking = SENSITIVE_DATA_MASKING_BASE.dup
144
+ @excluder = Contrast::Agent::Excluder.new
136
145
  end
137
146
 
138
147
  def build_protect_rules
@@ -202,9 +211,8 @@ module Contrast
202
211
  # @application_state.exclusion_matchers = new_vals[:exclusion_matchers]
203
212
  update_sensitive_data_policy(app_settings.sensitive_data_masking)
204
213
  @assess_state.disabled_assess_rules = app_settings.assess.disabled_rules
205
- if app_settings.assess.session_id && !app_settings.assess.session_id.blank?
206
- @assess_state.session_id = app_settings.assess.session_id
207
- end
214
+ new_session_id = app_settings.assess.session_id
215
+ @assess_state.session_id = new_session_id if new_session_id && !new_session_id.blank?
208
216
  @last_app_update_ms = Contrast::Utils::Timer.now_ms
209
217
  end
210
218
 
@@ -12,7 +12,7 @@ module Contrast
12
12
  extend Forwardable
13
13
  AT_UNDERSCORE = '@_'
14
14
 
15
- def to_hash
15
+ def to_contrast_hash
16
16
  hsh = {}
17
17
  instance_variables.each do |iv|
18
18
  # strip the '@' of '@_' to get the key
@@ -11,11 +11,12 @@ module Contrast
11
11
 
12
12
  attr_accessor :disabled_rules
13
13
  attr_writer :bot_blocker, :cmd_injection, :sql_injection, :nosql_injection, :untrusted_deserialization,
14
- :xxe, :path_traversal, :reflected_xss, :unsafe_file_upload, :rule_base
14
+ :xxe, :path_traversal, :reflected_xss, :unsafe_file_upload, :rule_base, :cmdi_command_backdoors,
15
+ :sqli_dangerous_function
15
16
 
16
17
  BASE_RULE = 'Contrast::Agent::Protect::Rule::Base'.cs__freeze
17
18
 
18
- def initialize hsh = {}
19
+ def initialize hsh = {} # rubocop:disable Metrics/AbcSize
19
20
  return unless hsh
20
21
 
21
22
  @disabled_rules = hsh[:disabled_rules]
@@ -27,8 +28,13 @@ module Contrast
27
28
  @path_traversal = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'path-traversal'])
28
29
  @reflected_xss = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'reflected-xss'])
29
30
  @sql_injection = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'sql-injection'])
31
+ @sqli_dangerous_function =
32
+ Contrast::Config::ProtectRuleConfiguration.new(hsh[:'sql-injection-semantic-dangerous-functions'])
30
33
  @unsafe_file_upload = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'unsafe-file-upload'])
31
34
  @untrusted_deserialization = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'untrusted-deserialization'])
35
+ @cmdi_command_backdoors = Contrast::Config::ProtectRuleConfiguration.new(hsh[
36
+ :'cmd-injection-command-backdoors'
37
+ ])
32
38
  @xxe = Contrast::Config::ProtectRuleConfiguration.new(hsh[:xxe])
33
39
  end
34
40
 
@@ -72,10 +78,18 @@ module Contrast
72
78
  @unsafe_file_upload ||= Contrast::Config::ProtectRuleConfiguration.new
73
79
  end
74
80
 
81
+ def cmdi_command_backdoors
82
+ @cmdi_command_backdoors ||= Contrast::Config::ProtectRuleConfiguration.new
83
+ end
84
+
75
85
  def rule_base
76
86
  @rule_base ||= Contrast::Config::ProtectRuleConfiguration.new
77
87
  end
78
88
 
89
+ def sqli_dangerous_function
90
+ @sqli_dangerous_function = Contrast::Config::ProtectRuleConfiguration.new
91
+ end
92
+
79
93
  def []= key, value
80
94
  instance_variable_set("@#{ convert_key(key) }".to_sym, value)
81
95
  end
@@ -90,7 +104,7 @@ module Contrast
90
104
 
91
105
  # Convert instance variable names to format expected by TS
92
106
  # for adding to the hash
93
- def to_hash
107
+ def to_contrast_hash
94
108
  hsh = {}
95
109
  instance_variables.each do |iv|
96
110
  # strip the '@' to get the key
@@ -9,7 +9,7 @@ module Contrast
9
9
  include Contrast::Config::BaseConfiguration
10
10
 
11
11
  # @return [String, nil]
12
- attr_accessor :name
12
+ attr_reader :name
13
13
  # @return [String, nil]
14
14
  attr_accessor :path
15
15
  # @return [String, nil]
@@ -11,13 +11,7 @@ module Contrast
11
11
  end
12
12
 
13
13
  require 'contrast/config/base_configuration'
14
- require 'contrast/config/service_configuration'
15
14
  require 'contrast/config/exception_configuration'
16
- require 'contrast/config/assess_rules_configuration'
17
15
  require 'contrast/config/protect_rule_configuration'
18
16
  require 'contrast/config/protect_rules_configuration'
19
-
20
- require 'contrast/config/ruby_configuration'
21
17
  require 'contrast/config/server_configuration'
22
- require 'contrast/config/assess_configuration'
23
- require 'contrast/config/root_configuration'
@@ -6,7 +6,15 @@ require 'fileutils'
6
6
 
7
7
  require 'contrast/config'
8
8
  require 'contrast/utils/object_share'
9
+ require 'contrast/components/agent'
10
+ require 'contrast/components/api'
11
+ require 'contrast/components/app_context'
9
12
  require 'contrast/components/scope'
13
+ require 'contrast/components/inventory'
14
+ require 'contrast/components/protect'
15
+ require 'contrast/components/assess'
16
+ require 'contrast/components/service'
17
+ require 'contrast/config/server_configuration'
10
18
 
11
19
  module Contrast
12
20
  # This is how we read in the local settings for the Agent, both ENV/ CMD line
@@ -18,7 +26,28 @@ module Contrast
18
26
  include Contrast::Components::Scope::InstanceMethods
19
27
  extend Contrast::Components::Scope::InstanceMethods
20
28
 
21
- attr_reader :default_name, :root
29
+ include Contrast::Config::BaseConfiguration
30
+
31
+ attr_reader :default_name
32
+
33
+ # @return [Contrast::Components::Api::Interface]
34
+ attr_writer :api
35
+ # @return [Contrast::Components::Agent::Interface]
36
+ attr_writer :agent
37
+ # @return [Contrast::Components::AppContext::Interface]
38
+ attr_writer :application
39
+ # @return [Contrast::Config::ServerConfiguration]
40
+ attr_writer :server
41
+ # @return [Contrast::Components::Assess::Interface]
42
+ attr_writer :assess
43
+ # @return [Contrast::Components::Inventory::Interface]
44
+ attr_writer :inventory
45
+ # @return [Contrast::Components::Protect::Interface]
46
+ attr_writer :protect
47
+ # @return [Contrast::Components::Service::Interface]
48
+ attr_writer :service
49
+ # @return [Boolean, nil]
50
+ attr_accessor :enable
22
51
 
23
52
  DEFAULT_YAML_PATH = 'contrast_security.yaml'
24
53
  MILLISECOND_MARKER = '_ms'
@@ -40,20 +69,15 @@ module Contrast
40
69
  # Some in-flight rewrites to maintain backwards compatibility
41
70
  config_kv = update_prop_keys(config_kv)
42
71
 
43
- @root = Contrast::Config::RootConfiguration.new(config_kv)
44
- end
45
-
46
- # Because we call this method to determine the need for scoping, it itself
47
- # must be executed inside a Contrast scope. Failure to do so could result
48
- # in an infinite loop on the to_sym method used later.
49
- def method_missing symbol, *args
50
- with_contrast_scope do
51
- root.public_send(symbol, *args) if root.cs__respond_to?(symbol)
52
- end
53
- end
54
-
55
- def respond_to_missing? method_name, *args
56
- root&.cs__respond_to?(method_name) || super
72
+ @api = Contrast::Components::Api::Interface.new(config_kv[:api])
73
+ @enable = config_kv[:enable]
74
+ @agent = Contrast::Components::Agent::Interface.new(config_kv[:agent])
75
+ @application = Contrast::Components::AppContext::Interface.new(config_kv[:application])
76
+ @server = Contrast::Config::ServerConfiguration.new(config_kv[:server])
77
+ @assess = Contrast::Components::Assess::Interface.new(config_kv[:assess])
78
+ @inventory = Contrast::Components::Inventory::Interface.new(config_kv[:inventory])
79
+ @protect = Contrast::Components::Protect::Interface.new(config_kv[:protect])
80
+ @service = Contrast::Components::Service::Interface.new(config_kv[:service])
57
81
  end
58
82
 
59
83
  # Get a loggable YAML format of this configuration
@@ -63,6 +87,46 @@ module Contrast
63
87
  convert_to_hash.to_yaml
64
88
  end
65
89
 
90
+ # @return [Contrast::Components::Api::Interface]
91
+ def api
92
+ @api ||= Contrast::Components::Api::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
93
+ end
94
+
95
+ # @return [Contrast::Components::Agent::Interface]
96
+ def agent
97
+ @agent ||= Contrast::Components::Agent::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
98
+ end
99
+
100
+ # @return [Contrast::Components::AppContext::Interface]
101
+ def application
102
+ @application ||= Contrast::Components::AppContext::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
103
+ end
104
+
105
+ # @return [Contrast::Config::ServerConfiguration]
106
+ def server
107
+ @server ||= Contrast::Config::ServerConfiguration.new # rubocop:disable Naming/MemoizedInstanceVariableName
108
+ end
109
+
110
+ # @return [Contrast::Components::Assess::Interface]
111
+ def assess
112
+ @assess ||= Contrast::Components::Assess::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
113
+ end
114
+
115
+ # @return [Contrast::Components::Inventory::Interface]
116
+ def inventory
117
+ @inventory ||= Contrast::Components::Inventory::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
118
+ end
119
+
120
+ # @return [Contrast::Components::Protect::Interface]
121
+ def protect
122
+ @protect ||= Contrast::Components::Protect::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
123
+ end
124
+
125
+ # @return [Contrast::Components::Service::Interface]
126
+ def service
127
+ @service ||= Contrast::Components::Service::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
128
+ end
129
+
66
130
  protected
67
131
 
68
132
  # TODO: RUBY-546 move utility methods to auxiliary classes
@@ -213,11 +277,11 @@ module Contrast
213
277
  # @return [Hash, Object] the leaf of each
214
278
  # Contrast::Config::BaseConfiguration will be returned in the N > 0 steps
215
279
  # the Hash will be returned at the end of the 0 level
216
- def convert_to_hash convert = root, hash = {}
280
+ def convert_to_hash convert = self, hash = {}
217
281
  case convert
218
282
  when Contrast::Config::BaseConfiguration
219
283
  # to_hash returns @configuration_map
220
- convert.to_hash.each_key do |key|
284
+ convert.to_contrast_hash.each_key do |key|
221
285
  # change '-' to '_' for ProtectRulesConfiguration
222
286
  hash[key] = convert_to_hash(convert.send(key.tr('-', '_').to_sym), {})
223
287
  hash[key] = REDACTED if redactable?(key)
@@ -19,7 +19,9 @@ module Contrast
19
19
  # source might not be all the args passed in, but it is the one we care
20
20
  # about. we could pass in all the args in the last param here if it
21
21
  # becomes an issue in rendering on TS
22
- Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node, source, Kernel, nil, source)
22
+ finding = Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node,
23
+ source, Kernel, nil, source)
24
+ Contrast::Agent::Assess::Policy::TriggerMethod.report_finding(finding) if finding
23
25
  end
24
26
 
25
27
  private
@@ -36,8 +36,9 @@ module Contrast
36
36
  # source might not be all the args passed in, but it is the one we care
37
37
  # about. we could pass in all the args in the last param here if it
38
38
  # becomes an issue in rendering on TS
39
- Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node('Marshal', :load), source,
40
- self, ret, *args)
39
+ finding = Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node('Marshal', :load),
40
+ source, self, ret, *args)
41
+ Contrast::Agent::Assess::Policy::TriggerMethod.report_finding(finding) if finding
41
42
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
42
43
 
43
44
  properties.copy_from(source, ret)
@@ -37,7 +37,6 @@ module Contrast
37
37
  # @param inputs [Array<String>] Inputs for interpolation.
38
38
  # @param result [String] The result from the interpolation.
39
39
  def track_interpolation inputs, result
40
- return unless ::Contrast::AGENT.interpolation_enabled?
41
40
  return unless inputs.any? { |input| Contrast::Agent::Assess::Tracker.tracked?(input) }
42
41
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(result))
43
42
 
@@ -36,7 +36,7 @@ module Contrast
36
36
  # conditions
37
37
  def assign_value path
38
38
  case path
39
- when /fiber/, /interpolation26/
39
+ when /fiber/, /interpolation/
40
40
  require(path) if Funchook.available?
41
41
  else
42
42
  require(path)
@@ -41,11 +41,6 @@ module Contrast
41
41
  raise(NoMethodError, 'Subclasses of BaseSupport should implement this method')
42
42
  end
43
43
 
44
- # @raise [NoMethodError] raises error if subclass does not implement this method
45
- def current_route
46
- raise(NoMethodError, 'Subclasses of BaseSupport should implement this method')
47
- end
48
-
49
44
  # @raise [NoMethodError] raises error if subclass does not implement this method
50
45
  def retrieve_request _env
51
46
  raise(NoMethodError, 'Subclasses of BaseSupport should implement this method')
@@ -68,29 +68,6 @@ module Contrast
68
68
  routes
69
69
  end
70
70
 
71
- # Given the current request return a RouteCoverage dtm.
72
- #
73
- # @param request [Contrast::Agent::Request] a contrast tracked request.
74
- # @param controller [::Grape::API] optionally use this controller instead of global ::Grape::API.
75
- # @return [Contrast::Api::Dtm::RouteCoverage, nil] a Dtm describing the route
76
- # matched to the request if a match was found.
77
- def current_route request, controller = ::Grape::API, full_route = nil
78
- return unless grape_controller?(controller)
79
-
80
- method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
81
-
82
- # Find final controller - actually we gotta match the route to the scanned application
83
- # Initially Grape compiles all routes on startup, so we can use the url from the request
84
- # and create the observed route
85
- # Class < Grape::API, Grape::Router::Route
86
- final_controller, route_pattern = _route_recurse(method, _cleaned_route(request), grape_controllers)
87
- return unless final_controller
88
-
89
- full_route ||= request.env[::Rack::PATH_INFO]
90
-
91
- Contrast::Api::Dtm::RouteCoverage.from_grape_controller(final_controller, method, route_pattern, full_route)
92
- end
93
-
94
71
  # Given the current request - return a RouteCoverage object
95
72
 
96
73
  # @param request [Contrast::Agent::Request] a contrast tracked request.
@@ -113,6 +90,7 @@ module Contrast
113
90
 
114
91
  new_route_coverage = Contrast::Agent::Reporting::RouteCoverage.new
115
92
  new_route_coverage.attach_rack_based_data(final_controller, method, route_pattern, full_route)
93
+ new_route_coverage
116
94
  end
117
95
 
118
96
  # Search object space for grape controllers--any class that subclasses ::Grape::API.
@@ -108,16 +108,6 @@ module Contrast
108
108
  result
109
109
  end
110
110
 
111
- # Iterate through current frameworks and return the current request's route. This will be the first non-nil
112
- # result.
113
- #
114
- # @param request [Contrast::Agent::Request] the current request.
115
- # @return [Contrast::Api::Dtm::RouteCoverage] the current route as a Dtm.
116
- def get_route_dtm request
117
- @_frameworks.lazy.map { |framework_support| framework_support.current_route(request) }.
118
- reject(&:nil?).first # rubocop:disable Style/CollectionCompact
119
- end
120
-
121
111
  # Iterate through current frameworks and return the current request's route. This will be the first non-nil
122
112
  # result.
123
113
  #