contrast-agent 5.3.0 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (306) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +1 -1
  3. data/Rakefile +1 -1
  4. data/ext/build_funchook.rb +3 -3
  5. data/ext/cs__assess_array/cs__assess_array.c +7 -0
  6. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +24 -6
  7. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
  8. data/ext/cs__assess_hash/cs__assess_hash.c +3 -4
  9. data/ext/cs__assess_kernel/cs__assess_kernel.c +1 -2
  10. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +26 -12
  11. data/ext/cs__assess_module/cs__assess_module.c +1 -1
  12. data/ext/cs__assess_regexp/cs__assess_regexp.c +15 -2
  13. data/ext/cs__assess_regexp/cs__assess_regexp.h +2 -0
  14. data/ext/cs__assess_string/cs__assess_string.c +21 -1
  15. data/ext/cs__assess_test/cs__assess_test.h +9 -0
  16. data/ext/cs__assess_test/cs__assess_tests.c +22 -0
  17. data/ext/cs__assess_test/extconf.rb +5 -0
  18. data/ext/cs__common/cs__common.c +113 -11
  19. data/ext/cs__common/cs__common.h +29 -5
  20. data/ext/cs__contrast_patch/cs__contrast_patch.c +55 -44
  21. data/ext/cs__os_information/cs__os_information.c +13 -10
  22. data/ext/cs__scope/cs__scope.c +146 -97
  23. data/ext/cs__tests/cs__tests.c +12 -0
  24. data/ext/cs__tests/cs__tests.h +3 -0
  25. data/ext/cs__tests/extconf.rb +5 -0
  26. data/ext/extconf_common.rb +1 -1
  27. data/lib/contrast/agent/assess/contrast_object.rb +16 -16
  28. data/lib/contrast/agent/assess/events/source_event.rb +17 -19
  29. data/lib/contrast/agent/assess/finalizers/hash.rb +4 -2
  30. data/lib/contrast/agent/assess/policy/policy.rb +9 -10
  31. data/lib/contrast/agent/assess/policy/policy_node.rb +58 -36
  32. data/lib/contrast/agent/assess/policy/policy_node_utils.rb +51 -0
  33. data/lib/contrast/agent/assess/policy/policy_scanner.rb +2 -16
  34. data/lib/contrast/agent/assess/policy/preshift.rb +8 -2
  35. data/lib/contrast/agent/assess/policy/propagation_method.rb +48 -14
  36. data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -3
  37. data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
  38. data/lib/contrast/agent/assess/policy/propagator/buffer.rb +119 -0
  39. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -1
  40. data/lib/contrast/agent/assess/policy/propagator/keep.rb +19 -4
  41. data/lib/contrast/agent/assess/policy/propagator/remove.rb +18 -2
  42. data/lib/contrast/agent/assess/policy/propagator/splat.rb +17 -3
  43. data/lib/contrast/agent/assess/policy/propagator/split.rb +17 -21
  44. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -1
  45. data/lib/contrast/agent/assess/policy/propagator/substitution_utils.rb +1 -1
  46. data/lib/contrast/agent/assess/policy/propagator/trim.rb +2 -2
  47. data/lib/contrast/agent/assess/policy/propagator.rb +1 -0
  48. data/lib/contrast/agent/assess/policy/source_method.rb +7 -7
  49. data/lib/contrast/agent/assess/policy/source_node.rb +1 -1
  50. data/lib/contrast/agent/assess/policy/trigger_method.rb +11 -17
  51. data/lib/contrast/agent/assess/policy/trigger_node.rb +16 -16
  52. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +1 -1
  53. data/lib/contrast/agent/assess/property/evented.rb +2 -2
  54. data/lib/contrast/agent/assess/property/tagged.rb +3 -3
  55. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +6 -8
  56. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +6 -7
  57. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +12 -7
  58. data/lib/contrast/agent/assess/rule/response/auto_complete_rule.rb +1 -1
  59. data/lib/contrast/agent/assess/rule/response/base_rule.rb +13 -6
  60. data/lib/contrast/agent/assess/rule/response/body_rule.rb +3 -3
  61. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +66 -43
  62. data/lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb +4 -4
  63. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +6 -6
  64. data/lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb +4 -4
  65. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +4 -4
  66. data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +1 -1
  67. data/lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb +4 -4
  68. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +3 -4
  69. data/lib/contrast/agent/assess/tag.rb +13 -14
  70. data/lib/contrast/agent/at_exit_hook.rb +12 -1
  71. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +0 -7
  72. data/lib/contrast/agent/deadzone/policy/policy.rb +0 -6
  73. data/lib/contrast/agent/exclusion_matcher.rb +3 -3
  74. data/lib/contrast/agent/inventory/database_config.rb +10 -3
  75. data/lib/contrast/agent/middleware.rb +10 -5
  76. data/lib/contrast/agent/patching/policy/after_load_patch.rb +3 -5
  77. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +2 -2
  78. data/lib/contrast/agent/patching/policy/method_policy_extend.rb +4 -4
  79. data/lib/contrast/agent/patching/policy/patch.rb +20 -19
  80. data/lib/contrast/agent/patching/policy/patch_status.rb +10 -3
  81. data/lib/contrast/agent/patching/policy/patcher.rb +4 -4
  82. data/lib/contrast/agent/patching/policy/policy.rb +13 -15
  83. data/lib/contrast/agent/patching/policy/policy_node.rb +32 -21
  84. data/lib/contrast/agent/patching/policy/trigger_node.rb +1 -1
  85. data/lib/contrast/agent/protect/exploitable_collection.rb +38 -0
  86. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +132 -75
  87. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +4 -3
  88. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +3 -3
  89. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
  90. data/lib/contrast/agent/protect/policy/rule_applicator.rb +4 -4
  91. data/lib/contrast/agent/protect/rule/base.rb +53 -9
  92. data/lib/contrast/agent/protect/rule/base_service.rb +31 -12
  93. data/lib/contrast/agent/protect/rule/cmd_injection.rb +23 -3
  94. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +83 -0
  95. data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +64 -0
  96. data/lib/contrast/agent/protect/rule/default_scanner.rb +2 -1
  97. data/lib/contrast/agent/protect/rule/deserialization.rb +18 -7
  98. data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +96 -0
  99. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +72 -46
  100. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +231 -0
  101. data/lib/contrast/agent/protect/rule/no_sqli.rb +28 -2
  102. data/lib/contrast/agent/protect/rule/path_traversal.rb +13 -3
  103. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +18 -54
  104. data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +2 -5
  105. data/lib/contrast/agent/protect/rule/sqli.rb +16 -23
  106. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +82 -0
  107. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +45 -0
  108. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +42 -0
  109. data/lib/contrast/agent/protect/rule/xss.rb +17 -0
  110. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +14 -13
  111. data/lib/contrast/agent/protect/rule/xxe.rb +25 -3
  112. data/lib/contrast/agent/reaction_processor.rb +1 -1
  113. data/lib/contrast/agent/reporting/attack_result/attack_result.rb +63 -0
  114. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +52 -0
  115. data/lib/contrast/agent/reporting/attack_result/response_type.rb +29 -0
  116. data/lib/contrast/agent/reporting/attack_result/user_input.rb +87 -0
  117. data/lib/contrast/agent/reporting/masker/masker.rb +243 -0
  118. data/lib/contrast/agent/reporting/masker/masker_utils.rb +62 -0
  119. data/lib/contrast/agent/reporting/report.rb +2 -0
  120. data/lib/contrast/agent/reporting/reporter.rb +29 -22
  121. data/lib/contrast/agent/reporting/reporter_heartbeat.rb +49 -0
  122. data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +34 -0
  123. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +51 -0
  124. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +96 -0
  125. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +70 -0
  126. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +182 -0
  127. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +56 -0
  128. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_stack.rb +22 -0
  129. data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +70 -0
  130. data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +13 -5
  131. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +60 -0
  132. data/lib/contrast/agent/reporting/reporting_events/application_reporting_event.rb +27 -0
  133. data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +44 -0
  134. data/lib/contrast/agent/reporting/reporting_events/application_startup_instrumentation.rb +27 -0
  135. data/lib/contrast/agent/reporting/reporting_events/application_update.rb +7 -12
  136. data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +1 -1
  137. data/lib/contrast/agent/reporting/reporting_events/finding.rb +10 -4
  138. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +2 -4
  139. data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +3 -3
  140. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +5 -5
  141. data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +6 -2
  142. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +16 -12
  143. data/lib/contrast/agent/reporting/reporting_events/poll.rb +6 -2
  144. data/lib/contrast/agent/reporting/reporting_events/preflight.rb +10 -8
  145. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +8 -11
  146. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +2 -1
  147. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +8 -6
  148. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +12 -20
  149. data/lib/contrast/agent/reporting/reporting_events/server_reporting_event.rb +27 -0
  150. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +17 -27
  151. data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +38 -0
  152. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +8 -0
  153. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +6 -0
  154. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -2
  155. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +29 -13
  156. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +64 -76
  157. data/lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb +1 -1
  158. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +17 -7
  159. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +100 -0
  160. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +75 -13
  161. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_mode.rb +63 -0
  162. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +163 -122
  163. data/lib/contrast/agent/reporting/settings/application_settings.rb +10 -1
  164. data/lib/contrast/agent/reporting/settings/assess.rb +5 -5
  165. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +7 -35
  166. data/lib/contrast/agent/reporting/settings/exclusions.rb +3 -3
  167. data/lib/contrast/agent/reporting/settings/protect.rb +21 -6
  168. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +6 -6
  169. data/lib/contrast/agent/reporting/settings/reaction.rb +3 -3
  170. data/lib/contrast/agent/reporting/settings/sampling.rb +36 -0
  171. data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +110 -0
  172. data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +58 -0
  173. data/lib/contrast/agent/reporting/settings/server_features.rb +2 -2
  174. data/lib/contrast/agent/request.rb +5 -5
  175. data/lib/contrast/agent/request_context.rb +25 -21
  176. data/lib/contrast/agent/request_context_extend.rb +12 -25
  177. data/lib/contrast/agent/request_handler.rb +7 -3
  178. data/lib/contrast/agent/response.rb +2 -0
  179. data/lib/contrast/agent/rule_set.rb +2 -2
  180. data/lib/contrast/agent/scope.rb +1 -1
  181. data/lib/contrast/agent/service_heartbeat.rb +6 -48
  182. data/lib/contrast/agent/static_analysis.rb +1 -1
  183. data/lib/contrast/agent/telemetry/base.rb +155 -0
  184. data/lib/contrast/agent/telemetry/events/event.rb +35 -0
  185. data/lib/contrast/agent/telemetry/events/exceptions/obfuscate.rb +119 -0
  186. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +59 -0
  187. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +44 -0
  188. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +115 -0
  189. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +83 -0
  190. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +64 -0
  191. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +20 -0
  192. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +30 -0
  193. data/lib/contrast/agent/telemetry/events/metric_event.rb +28 -0
  194. data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +123 -0
  195. data/lib/contrast/agent/thread_watcher.rb +52 -68
  196. data/lib/contrast/agent/version.rb +1 -1
  197. data/lib/contrast/agent/worker_thread.rb +8 -0
  198. data/lib/contrast/agent.rb +4 -3
  199. data/lib/contrast/api/communication/messaging_queue.rb +29 -12
  200. data/lib/contrast/api/communication/response_processor.rb +7 -10
  201. data/lib/contrast/api/communication/service_lifecycle.rb +1 -1
  202. data/lib/contrast/api/communication/socket.rb +1 -1
  203. data/lib/contrast/api/communication/socket_client.rb +1 -1
  204. data/lib/contrast/api/communication/speedracer.rb +3 -3
  205. data/lib/contrast/api/decorators/activity.rb +33 -0
  206. data/lib/contrast/api/decorators/address.rb +1 -1
  207. data/lib/contrast/api/decorators/agent_startup.rb +10 -9
  208. data/lib/contrast/api/decorators/application_settings.rb +1 -1
  209. data/lib/contrast/api/decorators/application_startup.rb +4 -4
  210. data/lib/contrast/api/decorators/http_request.rb +1 -1
  211. data/lib/contrast/api/decorators/response_type.rb +17 -0
  212. data/lib/contrast/api/decorators.rb +1 -0
  213. data/lib/contrast/components/agent.rb +1 -1
  214. data/lib/contrast/components/app_context.rb +0 -4
  215. data/lib/contrast/components/assess.rb +14 -0
  216. data/lib/contrast/components/base.rb +1 -1
  217. data/lib/contrast/components/config.rb +19 -28
  218. data/lib/contrast/components/contrast_service.rb +13 -1
  219. data/lib/contrast/components/protect.rb +2 -2
  220. data/lib/contrast/components/sampling.rb +8 -12
  221. data/lib/contrast/components/settings.rb +151 -19
  222. data/lib/contrast/config/agent_configuration.rb +34 -41
  223. data/lib/contrast/config/api_configuration.rb +16 -75
  224. data/lib/contrast/config/api_proxy_configuration.rb +9 -48
  225. data/lib/contrast/config/application_configuration.rb +24 -95
  226. data/lib/contrast/config/assess_configuration.rb +21 -76
  227. data/lib/contrast/config/assess_rules_configuration.rb +13 -38
  228. data/lib/contrast/config/base_configuration.rb +11 -76
  229. data/lib/contrast/config/certification_configuration.rb +15 -68
  230. data/lib/contrast/config/exception_configuration.rb +15 -59
  231. data/lib/contrast/config/heap_dump_configuration.rb +19 -73
  232. data/lib/contrast/config/inventory_configuration.rb +11 -55
  233. data/lib/contrast/config/logger_configuration.rb +8 -41
  234. data/lib/contrast/config/protect_configuration.rb +23 -10
  235. data/lib/contrast/config/protect_rule_configuration.rb +23 -37
  236. data/lib/contrast/config/protect_rules_configuration.rb +39 -43
  237. data/lib/contrast/config/request_audit_configuration.rb +16 -55
  238. data/lib/contrast/config/root_configuration.rb +71 -14
  239. data/lib/contrast/config/ruby_configuration.rb +14 -47
  240. data/lib/contrast/config/sampling_configuration.rb +12 -65
  241. data/lib/contrast/config/server_configuration.rb +13 -45
  242. data/lib/contrast/config/service_configuration.rb +18 -54
  243. data/lib/contrast/configuration.rb +25 -17
  244. data/lib/contrast/extension/assess/array.rb +1 -1
  245. data/lib/contrast/extension/assess/erb.rb +1 -1
  246. data/lib/contrast/extension/assess/marshal.rb +1 -1
  247. data/lib/contrast/extension/assess/string.rb +20 -1
  248. data/lib/contrast/extension/extension.rb +2 -2
  249. data/lib/contrast/extension/module.rb +0 -1
  250. data/lib/contrast/framework/base_support.rb +8 -8
  251. data/lib/contrast/framework/grape/support.rb +3 -3
  252. data/lib/contrast/framework/manager.rb +7 -7
  253. data/lib/contrast/framework/manager_extend.rb +1 -1
  254. data/lib/contrast/framework/rack/patch/session_cookie.rb +1 -1
  255. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +14 -3
  256. data/lib/contrast/framework/rails/patch/assess_configuration.rb +3 -3
  257. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +1 -1
  258. data/lib/contrast/framework/rails/patch/support.rb +14 -46
  259. data/lib/contrast/framework/rails/support.rb +2 -2
  260. data/lib/contrast/framework/sinatra/support.rb +1 -1
  261. data/lib/contrast/logger/aliased_logging.rb +94 -0
  262. data/lib/contrast/logger/application.rb +1 -5
  263. data/lib/contrast/logger/cef_log.rb +15 -15
  264. data/lib/contrast/logger/format.rb +1 -1
  265. data/lib/contrast/logger/log.rb +8 -8
  266. data/lib/contrast/tasks/config.rb +100 -4
  267. data/lib/contrast/tasks/service.rb +2 -2
  268. data/lib/contrast/utils/assess/object_store.rb +36 -0
  269. data/lib/contrast/utils/assess/propagation_method_utils.rb +6 -0
  270. data/lib/contrast/utils/assess/tracking_util.rb +4 -4
  271. data/lib/contrast/utils/class_util.rb +9 -22
  272. data/lib/contrast/utils/findings.rb +3 -3
  273. data/lib/contrast/utils/hash_digest.rb +6 -7
  274. data/lib/contrast/utils/head_dump_utils_extend.rb +1 -1
  275. data/lib/contrast/utils/input_classification.rb +73 -0
  276. data/lib/contrast/utils/invalid_configuration_util.rb +2 -2
  277. data/lib/contrast/utils/log_utils.rb +7 -5
  278. data/lib/contrast/utils/lru_cache.rb +1 -1
  279. data/lib/contrast/utils/metrics_hash.rb +1 -1
  280. data/lib/contrast/utils/middleware_utils.rb +15 -14
  281. data/lib/contrast/utils/net_http_base.rb +5 -5
  282. data/lib/contrast/utils/object_share.rb +2 -1
  283. data/lib/contrast/utils/os.rb +1 -6
  284. data/lib/contrast/utils/patching/policy/patch_utils.rb +6 -7
  285. data/lib/contrast/utils/request_utils.rb +2 -2
  286. data/lib/contrast/utils/response_utils.rb +18 -33
  287. data/lib/contrast/utils/sha256_builder.rb +4 -4
  288. data/lib/contrast/utils/stack_trace_utils.rb +31 -13
  289. data/lib/contrast/utils/telemetry.rb +22 -7
  290. data/lib/contrast/utils/telemetry_client.rb +28 -16
  291. data/lib/contrast/utils/telemetry_hash.rb +41 -0
  292. data/lib/contrast/utils/telemetry_identifier.rb +18 -3
  293. data/lib/contrast/utils/timer.rb +1 -1
  294. data/lib/contrast.rb +9 -0
  295. data/resources/assess/policy.json +99 -1
  296. data/resources/deadzone/policy.json +0 -86
  297. data/ruby-agent.gemspec +10 -9
  298. data/service_executables/VERSION +1 -1
  299. data/service_executables/linux/contrast-service +0 -0
  300. data/service_executables/mac/contrast-service +0 -0
  301. metadata +99 -29
  302. data/lib/contrast/agent/metric_telemetry_event.rb +0 -26
  303. data/lib/contrast/agent/startup_metrics_telemetry_event.rb +0 -121
  304. data/lib/contrast/agent/telemetry.rb +0 -137
  305. data/lib/contrast/agent/telemetry_event.rb +0 -33
  306. data/lib/contrast/utils/exclude_key.rb +0 -20
@@ -17,13 +17,6 @@ module Contrast
17
17
  class CacheControl < HeaderRule
18
18
  include BodyRule
19
19
  include Framework::RailsSupport
20
-
21
- def rule_id
22
- 'cache-controls-missing'
23
- end
24
-
25
- protected
26
-
27
20
  HEADER_KEYS = %w[Cache-Control].cs__freeze
28
21
  ACCEPTED_VALUES = [/no-store/, /no-cache/].cs__freeze
29
22
  DEFAULT_SAFE = false
@@ -31,55 +24,75 @@ module Contrast
31
24
  HEAD_TAG = /<head>/i.cs__freeze
32
25
  NAME = 'cache-control'
33
26
 
27
+ def rule_id
28
+ 'cache-controls-missing'
29
+ end
30
+
31
+ protected
32
+
34
33
  # Determine if the Response violates the Rule or not. If it does, return the evidence that proves it so.
35
34
  #
36
35
  # @param response [Contrast::Agent::Response] the response of the application
37
36
  # @return [Hash, nil] the evidence required to prove the violation of the rule
38
37
  def violated? response
39
- has_header, evidence = process_header(response)
40
- return evidence unless evidence.nil?
38
+ return unless header?(response) && meta_tag?(response)
39
+
40
+ header_evidence = header_evidence(response)
41
+ return if header_evidence.nil?
41
42
 
42
- has_tag, evidence = process_body(response)
43
- return evidence unless evidence.nil?
44
- return {} if !has_header && !has_tag
43
+ tag_evidence = tag_evidence(response)
44
+ return if tag_evidence.nil?
45
45
 
46
- nil
46
+ { DATA => [header_evidence, tag_evidence] }
47
47
  end
48
48
 
49
- # Process Header value to determine if it violates rule
49
+ # Is a cache-control header available?
50
50
  # @param response [Contrast::Agent::Response] the response of the application
51
- # @return [Array[Boolean, Hash]] whether the header exists and the evidence hash or nil
52
- def process_header response
53
- # Rails 7 adds support for the cache_control header directly in the
54
- # rack response, we should use that value
55
- if framework_supported?
56
- cache_control = response.rack_response.cache_control
57
- has_header = !cache_control.empty?
58
- not_valid = has_header && !((cache_control[:no_cache]) || (cache_control[:no_store]))
59
- # evidence requires header value string, pull directly instead of rebuilding from hash
60
- return has_header, evidence(HEADER_TYPE, NAME, cache_control_to_s(cache_control)) if not_valid
61
- else
62
- # This rule is violated if the header is not there is there,
63
- # but the value is not 'no-store' or 'no-cache'
64
- cache_control = get_header_value(response)
65
- has_header = !!cache_control
66
- not_valid = has_header && !valid_header?(cache_control)
67
- return has_header, evidence(HEADER_TYPE, NAME, cache_control) if not_valid
51
+ # @return [Boolean]
52
+ def header? response
53
+ cache_control = cache_control_from(response)
54
+ framework_supported? ? !cache_control.blank? : !!cache_control
55
+ end
56
+
57
+ # Is a cache-control meta tag available?
58
+ # @param response [Contrast::Agent::Response] the response of the application
59
+ # @return [Boolean]
60
+ def meta_tag? response
61
+ return false if meta_tags(response).empty?
62
+
63
+ meta_tags(response).each do |tag|
64
+ return true if meta_cache_tag?(tag[HTML_PROP])
68
65
  end
69
- [has_header, nil]
66
+
67
+ false
68
+ end
69
+
70
+ def meta_tags response
71
+ return @_meta_tags if defined? @meta_tags
72
+
73
+ @_meta_tags = html_elements(response.body&.split(HEAD_TAG)&.last, META_START_STR)
74
+ end
75
+
76
+ # Process Header value to determine if it violates rule
77
+ # @param response [Contrast::Agent::Response] the response of the application
78
+ # @return [Hash, nil] the evidence hash or nil
79
+ def header_evidence response
80
+ cache_control = cache_control_from(response)
81
+ value = framework_supported? ? cache_control : cache_control_to_s(cache_control)
82
+ # If header is valid, then this portion of the rule isn't violated.
83
+ return if valid_header?(value)
84
+
85
+ # evidence requires header value string, pull directly instead of rebuilding from hash
86
+ evidence(HEADER_TYPE, NAME, value)
70
87
  end
71
88
 
72
- # Process Body to determine cache control exists as meta tag and if it violates rule
89
+ # Process Body to determine if cache control meta tag violates rule
73
90
  # @param response [Contrast::Agent::Response] the response of the application
74
- # @return [Array[Boolean, Hash]] whether the meta tags exists and the evidence hash or nil
75
- def process_body response
76
- body = response.body
77
- # check if the meta tag is include it
78
- meta_tags = html_elements(body&.split(HEAD_TAG)&.last, META_START_STR)
79
- meta_tags.each do |tag|
80
- return true, evidence(META_TYPE, PRAGMA, tag[HTML_PROP]) if meta_cache_tag? tag[HTML_PROP]
91
+ # @return [Hash, nil] the evidence hash or nil
92
+ def tag_evidence response
93
+ meta_tags(response).each do |tag|
94
+ return evidence(META_TYPE, PRAGMA, tag[HTML_PROP]) if meta_cache_tag?(tag[HTML_PROP])
81
95
  end
82
- [!meta_tags.empty?, nil]
83
96
  end
84
97
 
85
98
  def potential_elements section, element_start
@@ -121,13 +134,23 @@ module Contrast
121
134
  end
122
135
 
123
136
  # This method accepts the violation and transforms it to the proper hash
124
- # before return in as violation
137
+ # before returning a violation
125
138
  #
126
139
  # @param type [String] String of Header or META of the type
127
140
  # @param name [String] String of either cache-control or pragma
128
141
  # @param value [String] String of the violated value
129
142
  def evidence type, name, value
130
- { DATA => { type: type, name: name, value: value }.to_s }
143
+ { type: type, name: name, value: value }.to_json
144
+ end
145
+
146
+ def cache_control_from response
147
+ # Rails 7 adds support for the cache_control header directly in the
148
+ # rack response, we should use that value
149
+ if framework_supported? && response.rack_response.cs__is_a?(Rack::Response)
150
+ response.rack_response.cache_control
151
+ else
152
+ get_header_value(response)
153
+ end
131
154
  end
132
155
 
133
156
  # Rebuilds the String value of the Cache-Control Header
@@ -11,13 +11,13 @@ module Contrast
11
11
  module Response
12
12
  # These rules check the content of the HTTP Response to determine if the headers contains the required header
13
13
  class ClickJacking < HeaderRule
14
- def rule_id
15
- 'clickjacking-control-missing'
16
- end
17
-
18
14
  HEADER_KEYS = %w[X-Frame-Options].cs__freeze
19
15
  ACCEPTED_VALUES = [/^deny/i, /^sameorigin/i].cs__freeze
20
16
  DEFAULT_SAFE = false
17
+
18
+ def rule_id
19
+ 'clickjacking-control-missing'
20
+ end
21
21
  end
22
22
  end
23
23
  end
@@ -12,12 +12,6 @@ module Contrast
12
12
  module Response
13
13
  # These rules check that the HTTP Headers include CSP header types
14
14
  class CspHeaderInsecure < HeaderRule
15
- def rule_id
16
- 'csp-header-insecure'
17
- end
18
-
19
- protected
20
-
21
15
  HEADER_KEYS = %w[Content-Security-Policy X-Content-Security-Policy X-Webkit-CSP].cs__freeze
22
16
  DEFAULT_SAFE = false
23
17
  SETTINGS = %w[
@@ -28,6 +22,12 @@ module Contrast
28
22
  ASTERISK_REGEXP = /[*]/.cs__freeze
29
23
  SAFE_REFLECTED_XSS = /1/.cs__freeze
30
24
 
25
+ def rule_id
26
+ 'csp-header-insecure'
27
+ end
28
+
29
+ protected
30
+
31
31
  # Determine if the Response violates the Rule or not. If it does, return the evidence that proves it so.
32
32
  #
33
33
  # @param response [Contrast::Agent::Response] the response of the application
@@ -11,13 +11,13 @@ module Contrast
11
11
  module Response
12
12
  # These rules check that the HTTP Headers include CSP header types
13
13
  class CspHeaderMissing < HeaderRule
14
- def rule_id
15
- 'csp-header-missing'
16
- end
17
-
18
14
  HEADER_KEYS = %w[Content-Security-Policy X-Content-Security-Policy X-Webkit-CSP].cs__freeze
19
15
  ACCEPTED_VALUES = [/(.)/].cs__freeze
20
16
  DEFAULT_SAFE = false
17
+
18
+ def rule_id
19
+ 'csp-header-missing'
20
+ end
21
21
  end
22
22
  end
23
23
  end
@@ -12,16 +12,16 @@ module Contrast
12
12
  # This rule checks if the HTTP Headers include HSTS header and ensures that the max-age value
13
13
  # is set to a value greater than 0.
14
14
  class HSTSHeader < HeaderRule
15
+ HEADER_KEYS = %w[Strict-Transport-Security].cs__freeze
16
+ ACCEPTED_VALUES = [/max-age=(\.)?\d+(\.\d*)?/].cs__freeze
17
+ DEFAULT_SAFE = true
18
+
15
19
  def rule_id
16
20
  'hsts-header-missing'
17
21
  end
18
22
 
19
23
  protected
20
24
 
21
- HEADER_KEYS = %w[Strict-Transport-Security].cs__freeze
22
- ACCEPTED_VALUES = [/max-age=(\.)?\d+(\.\d*)?/].cs__freeze
23
- DEFAULT_SAFE = true
24
-
25
25
  def evidence data
26
26
  # get only the value of the max-age property
27
27
  val = data&.split('=')&.last
@@ -32,7 +32,7 @@ module Contrast
32
32
  # @return [Hash, nil] the evidence required to prove the violation of the rule
33
33
  def violated? response
34
34
  body = response.body
35
- forms = html_elements(body, FORM_START_REGEXP, true)
35
+ forms = html_elements(body, FORM_START_REGEXP, capture_overflow: true)
36
36
  forms.each do |form|
37
37
  # Because TeamServer will reject any subsequent form on the same page due to deduplication, we can
38
38
  # skip out on the first violation.
@@ -11,13 +11,13 @@ module Contrast
11
11
  module Response
12
12
  # These rules check the content of the HTTP Response to determine if the response contains the needed header
13
13
  class XContentType < HeaderRule
14
- def rule_id
15
- 'xcontenttype-header-missing'
16
- end
17
-
18
14
  HEADER_KEYS = %w[X-Content-Type-Options].cs__freeze
19
15
  ACCEPTED_VALUES = [/^nosniff/i].cs__freeze
20
16
  DEFAULT_SAFE = false
17
+
18
+ def rule_id
19
+ 'xcontenttype-header-missing'
20
+ end
21
21
  end
22
22
  end
23
23
  end
@@ -13,15 +13,14 @@ module Contrast
13
13
  # These rules check the content of the HTTP Response to determine if the response contains the needed header
14
14
  class XXssProtection < HeaderRule
15
15
  include Framework::RailsSupport
16
+ HEADER_KEYS = %w[X-XSS-Protection].cs__freeze
17
+ ACCEPTED_VALUES = [/^1/].cs__freeze
18
+ DEFAULT_SAFE = true
16
19
 
17
20
  def rule_id
18
21
  'xxssprotection-header-disabled'
19
22
  end
20
23
 
21
- HEADER_KEYS = %w[X-XSS-Protection].cs__freeze
22
- ACCEPTED_VALUES = [/^1/].cs__freeze
23
- DEFAULT_SAFE = true
24
-
25
24
  protected
26
25
 
27
26
  def analyze_response? response
@@ -12,6 +12,19 @@ module Contrast
12
12
  :start_idx, # start of range
13
13
  :end_idx # end of range (calculated from start + length), exclusive
14
14
 
15
+ # Update range should be how start and end index of tags are changed,
16
+ # as it includes validation
17
+ #
18
+ # Note that we allow start_idx == end_idx b/c this is how we determine
19
+ # if a tag range is 'covered' in trigger detection
20
+ ERROR_NEGATIVE_START = 'Unable to set start idx negative'
21
+ BELOW = 'BELOW'
22
+ ERROR_END_BEFORE_START = 'Unable to set start idx after end idx'
23
+ LOW_SPAN = 'LOW_SPAN'
24
+ WITHIN = 'WITHIN'
25
+ WITHOUT = 'WITHOUT'
26
+ HIGH_SPAN = 'HIGH_SPAN'
27
+ ABOVE = 'ABOVE'
15
28
  # Initialize a new tag
16
29
  #
17
30
  # @param label [String] the label of the tag
@@ -109,13 +122,6 @@ module Contrast
109
122
  end
110
123
  alias_method :to_s, :str_val
111
124
 
112
- BELOW = 'BELOW'
113
- LOW_SPAN = 'LOW_SPAN'
114
- WITHIN = 'WITHIN'
115
- WITHOUT = 'WITHOUT'
116
- HIGH_SPAN = 'HIGH_SPAN'
117
- ABOVE = 'ABOVE'
118
-
119
125
  # The tag is ______ the range
120
126
  # rrrrrrr == self.range, the range of the tag
121
127
  def compare_range start, stop
@@ -154,13 +160,6 @@ module Contrast
154
160
 
155
161
  private
156
162
 
157
- # Update range should be how start and end index of tags are changed,
158
- # as it includes validation
159
- #
160
- # Note that we allow start_idx == end_idx b/c this is how we determine
161
- # if a tag range is 'covered' in trigger detection
162
- ERROR_NEGATIVE_START = 'Unable to set start idx negative'
163
- ERROR_END_BEFORE_START = 'Unable to set start idx after end idx'
164
163
  def update_range start_idx, end_idx
165
164
  raise(ArgumentError, ERROR_NEGATIVE_START) if start_idx.negative?
166
165
  raise(ArgumentError, ERROR_END_BEFORE_START) if end_idx < start_idx
@@ -31,7 +31,18 @@ module Contrast
31
31
  context = Contrast::Agent::REQUEST_TRACKER.current
32
32
  return unless context
33
33
 
34
- Contrast::Agent.messaging_queue.send_event_immediately(context.activity)
34
+ if Contrast::Agent::Reporter.enabled?
35
+ [
36
+ context.new_observed_route,
37
+ Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.server_activity),
38
+ Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity.library_usages),
39
+ Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity)
40
+ ].each do |event|
41
+ Contrast::Agent.reporter&.send_event_immediately(event)
42
+ end
43
+ else
44
+ Contrast::Agent.messaging_queue&.send_event_immediately(context.activity)
45
+ end
35
46
  end
36
47
  end
37
48
  end
@@ -24,13 +24,6 @@ module Contrast
24
24
  def method_scope
25
25
  :contrast
26
26
  end
27
-
28
- # TODO: RUBY-99999 remove, used to clean up logs while debugging
29
- # def validate
30
- # return if class_name
31
- #
32
- # raise(ArgumentError, "#{ node_class } #{ id } did not have a proper class name. Unable to create.")
33
- # end
34
27
  end
35
28
  end
36
29
  end
@@ -35,12 +35,6 @@ module Contrast
35
35
  end
36
36
  end
37
37
 
38
- def validate
39
- return if class_name
40
-
41
- raise(ArgumentError, "#{ node_class } #{ id } did not have a proper class name. Unable to create.")
42
- end
43
-
44
38
  def module_names
45
39
  @_module_names ||= Set.new(deadzones.map(&:class_name))
46
40
  end
@@ -51,7 +51,7 @@ module Contrast
51
51
 
52
52
  @urls = []
53
53
  @exclusion.urls.each do |url|
54
- url_pattern = build_regexp(url, true, true)
54
+ url_pattern = build_regexp(url, start_anchor: true, end_anchor: true)
55
55
  @urls << url_pattern if url_pattern
56
56
  end
57
57
  end
@@ -66,7 +66,7 @@ module Contrast
66
66
  @wildcard_exclusions = []
67
67
  @exclusion.denylist.each do |code|
68
68
  class_name, method_name = code.split(Contrast::Utils::ObjectShare::COLON)
69
- class_pattern = build_regexp(class_name, false, true)
69
+ class_pattern = build_regexp(class_name, start_anchor: false, end_anchor: true)
70
70
  method_pattern = build_regexp(method_name)
71
71
  next unless class_pattern && method_pattern
72
72
 
@@ -74,7 +74,7 @@ module Contrast
74
74
  end
75
75
  end
76
76
 
77
- def build_regexp pattern, start_anchor = false, end_anchor = false
77
+ def build_regexp pattern, start_anchor: false, end_anchor: false
78
78
  pattern = Contrast::Utils::ObjectShare::CARROT + pattern if start_anchor
79
79
  pattern += Contrast::Utils::ObjectShare::DOLLAR_SIGN if end_anchor
80
80
  Regexp.compile(pattern)
@@ -44,20 +44,27 @@ module Contrast
44
44
  end
45
45
  end
46
46
  rescue StandardError => e
47
- logger.error('Unable to append db config', e)
47
+ logger.warn('Unable to append db config', e)
48
48
  nil
49
49
  end
50
50
 
51
51
  private
52
52
 
53
53
  # We capture the active record configuration used by this application, as reported by
54
- # ActiveRecord::Base.connection_config, so that we can record it once and report it as needed.
54
+ # ActiveRecord::Base.connection_db_config, so that we can record it once and report it as needed.
55
55
  #
56
56
  # @return [Hash]
57
57
  def active_record_config
58
58
  return @_active_record_config if instance_variable_defined?(:@_active_record_config)
59
59
 
60
- @_active_record_config = ActiveRecord::Base.connection_config rescue nil # rubocop:disable Style/RescueModifier
60
+ @_active_record_config = if ActiveRecord::Base.cs__respond_to?(:connection_db_config)
61
+ ActiveRecord::Base.connection_db_config
62
+ else
63
+ # TODO: RUBY-99999 - Remove when Rails 6.0 is not supported
64
+ ActiveRecord::Base.connection_config
65
+ end
66
+ rescue StandardError
67
+ nil
61
68
  end
62
69
 
63
70
  # The classes we instrument in order to determine which, if any, database(s) an application connects to take
@@ -13,7 +13,7 @@ require 'contrast/utils/heap_dump_util'
13
13
  require 'contrast/utils/telemetry'
14
14
  require 'contrast/agent/request_handler'
15
15
  require 'contrast/agent/static_analysis'
16
- require 'contrast/agent/startup_metrics_telemetry_event'
16
+ require 'contrast/agent/telemetry/events/startup_metrics_event'
17
17
  require 'contrast/utils/middleware_utils'
18
18
 
19
19
  require 'contrast/utils/timer'
@@ -48,6 +48,9 @@ module Contrast
48
48
  return
49
49
  end
50
50
  agent_startup_routine
51
+ rescue StandardError => e
52
+ logger.error('Unable to initialize the agent. Disabling permanently.', e)
53
+ ::Contrast::AGENT.disable! # ensure the agent is disabled (probably redundant)
51
54
  end
52
55
 
53
56
  # This is where we're hooked into the middleware stack. If the agent is enabled, we're ready to do some
@@ -78,9 +81,9 @@ module Contrast
78
81
  Contrast::Agent.thread_watcher.ensure_running?
79
82
  end
80
83
 
81
- if Contrast::Agent::Telemetry.enabled?
84
+ if Contrast::Agent::Telemetry::Base.enabled?
82
85
  logger.debug_with_time('middleware: sending startup metrics telemetry event') do
83
- event = Contrast::Agent::StartupMetricsTelemetryEvent.new
86
+ event = Contrast::Agent::Telemetry::StartupMetricsEvent.new
84
87
  Contrast::Agent.thread_watcher.telemetry_queue.send_event(event)
85
88
  end
86
89
  end
@@ -145,7 +148,7 @@ module Contrast
145
148
  request_handler.ruleset.prefilter
146
149
  end
147
150
  rescue StandardError => e
148
- raise e if security_exception?(e)
151
+ raise(e) if security_exception?(e)
149
152
 
150
153
  logger.error('Unable to execute agent pre_call', e)
151
154
  end
@@ -163,6 +166,8 @@ module Contrast
163
166
 
164
167
  # Build and report all collected findings prior response
165
168
  Contrast::Agent::FINDINGS.report_collected_findings unless Contrast::Agent::FINDINGS.collection.empty?
169
+ # All protect rules, which are trigger but require response to be reported
170
+ Contrast::Agent::EXPLOITS.report_recorded_exploits(context) unless Contrast::Agent::EXPLOITS.collection.empty?
166
171
 
167
172
  if Contrast::Agent.framework_manager.streaming?(env)
168
173
  context.reset_activity
@@ -175,7 +180,7 @@ module Contrast
175
180
  end
176
181
  # unsuccessful attack
177
182
  rescue StandardError => e
178
- raise e if security_exception?(e)
183
+ raise(e) if security_exception?(e)
179
184
 
180
185
  logger.error('Unable to execute agent post_call', e)
181
186
  end
@@ -47,7 +47,7 @@ module Contrast
47
47
  return true unless target_defined? # bc no methods are loaded
48
48
  return false unless method_to_instrument
49
49
 
50
- !module_lookup.instance_methods.include? method_to_instrument
50
+ !module_lookup.instance_methods.include?(method_to_instrument)
51
51
  end
52
52
 
53
53
  def applies? loaded_module_name
@@ -59,9 +59,7 @@ module Contrast
59
59
  end
60
60
 
61
61
  def instrument!
62
- return if instrumenting_module == :'Contrast::Framework::Rails::Rewrite' && RAILS_VER >= '2.6.0'
63
-
64
- require instrumentation_file_path
62
+ require(instrumentation_file_path)
65
63
 
66
64
  if instrumenting_module
67
65
  mod = Module.cs__const_get(instrumenting_module)
@@ -74,7 +72,7 @@ module Contrast
74
72
 
75
73
  def module_lookup
76
74
  @_module_lookup ||= begin
77
- Module.cs__const_get module_name
75
+ Module.cs__const_get(module_name)
78
76
  rescue StandardError => _e
79
77
  nil
80
78
  end
@@ -43,7 +43,7 @@ module Contrast
43
43
  ].cs__freeze
44
44
  paths.each do |p|
45
45
  path_part = "cs__assess_#{ p }"
46
- Contrast::Extension::Assess::InstrumentHelper.instrument "#{ path_part }/#{ path_part }"
46
+ Contrast::Extension::Assess::InstrumentHelper.instrument("#{ path_part }/#{ path_part }")
47
47
  end
48
48
  true
49
49
  end
@@ -73,7 +73,7 @@ module Contrast
73
73
  # handling
74
74
  def apply_require_patches!
75
75
  @_apply_require_patches ||= begin
76
- require 'contrast/extension/thread'
76
+ require('contrast/extension/thread')
77
77
  true
78
78
  rescue LoadError, StandardError => e
79
79
  logger.error('failed instrumenting apply_require_patches!', e)
@@ -38,8 +38,8 @@ module Contrast
38
38
  deadzone_node: deadzone_node
39
39
  })
40
40
 
41
- return method_policy unless check_method_policy_nodes_empty? source_node, propagation_node, trigger_node,
42
- protect_node, inventory_node, deadzone_node
41
+ return method_policy unless check_method_policy_nodes_empty?(source_node, propagation_node, trigger_node,
42
+ protect_node, inventory_node, deadzone_node)
43
43
 
44
44
  create_new_node(module_policy, method_policy) if module_policy.deadzone_nodes&.any?
45
45
  method_policy
@@ -74,9 +74,9 @@ module Contrast
74
74
  next unless node.method_name.nil?
75
75
 
76
76
  klass = Module.cs__const_get(node.class_name)
77
- next unless it_defined? klass, method_policy.method_name
77
+ next unless it_defined?(klass, method_policy.method_name)
78
78
 
79
- new_node = set_new_node method_policy, klass, node
79
+ new_node = set_new_node(method_policy, klass, node)
80
80
  method_policy.instance_variable_set(:@method_visibility, new_node.method_visibility)
81
81
  method_policy.instance_variable_set(:@deadzone_node, node)
82
82
  module_policy.deadzone_nodes << new_node