contrast-agent 4.3.2 → 4.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 (317) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +1 -1
  3. data/.simplecov +1 -1
  4. data/Gemfile +1 -1
  5. data/LICENSE.txt +1 -1
  6. data/Rakefile +2 -3
  7. data/exe/contrast_service +1 -1
  8. data/ext/build_funchook.rb +4 -4
  9. data/ext/cs__assess_active_record_named/cs__active_record_named.c +1 -1
  10. data/ext/cs__assess_active_record_named/extconf.rb +1 -1
  11. data/ext/cs__assess_array/cs__assess_array.c +1 -1
  12. data/ext/cs__assess_array/extconf.rb +1 -1
  13. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +1 -1
  14. data/ext/cs__assess_basic_object/extconf.rb +1 -1
  15. data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
  16. data/ext/cs__assess_fiber_track/extconf.rb +1 -1
  17. data/ext/cs__assess_hash/cs__assess_hash.c +4 -2
  18. data/ext/cs__assess_hash/extconf.rb +1 -1
  19. data/ext/cs__assess_kernel/cs__assess_kernel.c +1 -1
  20. data/ext/cs__assess_kernel/extconf.rb +1 -1
  21. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +1 -1
  22. data/ext/cs__assess_marshal_module/extconf.rb +1 -1
  23. data/ext/cs__assess_module/cs__assess_module.c +1 -1
  24. data/ext/cs__assess_module/extconf.rb +1 -1
  25. data/ext/cs__assess_regexp/cs__assess_regexp.c +1 -1
  26. data/ext/cs__assess_regexp/extconf.rb +1 -1
  27. data/ext/cs__assess_string/cs__assess_string.c +1 -1
  28. data/ext/cs__assess_string/extconf.rb +1 -1
  29. data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +1 -1
  30. data/ext/cs__assess_string_interpolation26/extconf.rb +1 -1
  31. data/ext/cs__assess_yield_track/cs__assess_yield_track.c +1 -1
  32. data/ext/cs__assess_yield_track/extconf.rb +1 -1
  33. data/ext/cs__common/cs__common.c +5 -5
  34. data/ext/cs__common/cs__common.h +4 -4
  35. data/ext/cs__common/extconf.rb +1 -1
  36. data/ext/cs__contrast_patch/cs__contrast_patch.c +22 -25
  37. data/ext/cs__contrast_patch/extconf.rb +1 -1
  38. data/ext/cs__protect_kernel/cs__protect_kernel.c +1 -1
  39. data/ext/cs__protect_kernel/extconf.rb +1 -1
  40. data/ext/extconf_common.rb +2 -6
  41. data/lib/contrast-agent.rb +1 -1
  42. data/lib/contrast.rb +20 -1
  43. data/lib/contrast/agent.rb +6 -4
  44. data/lib/contrast/agent/assess.rb +2 -11
  45. data/lib/contrast/agent/assess/contrast_event.rb +54 -71
  46. data/lib/contrast/agent/assess/contrast_object.rb +7 -4
  47. data/lib/contrast/agent/assess/events/event_factory.rb +3 -2
  48. data/lib/contrast/agent/assess/events/source_event.rb +7 -2
  49. data/lib/contrast/agent/assess/finalizers/freeze.rb +1 -1
  50. data/lib/contrast/agent/assess/finalizers/hash.rb +33 -34
  51. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +34 -16
  52. data/lib/contrast/agent/assess/policy/patcher.rb +11 -18
  53. data/lib/contrast/agent/assess/policy/policy.rb +1 -1
  54. data/lib/contrast/agent/assess/policy/policy_node.rb +26 -34
  55. data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
  56. data/lib/contrast/agent/assess/policy/preshift.rb +4 -2
  57. data/lib/contrast/agent/assess/policy/propagation_method.rb +32 -30
  58. data/lib/contrast/agent/assess/policy/propagation_node.rb +20 -9
  59. data/lib/contrast/agent/assess/policy/propagator.rb +1 -1
  60. data/lib/contrast/agent/assess/policy/propagator/append.rb +29 -14
  61. data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
  62. data/lib/contrast/agent/assess/policy/propagator/center.rb +3 -2
  63. data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
  64. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +22 -17
  65. data/lib/contrast/agent/assess/policy/propagator/insert.rb +4 -2
  66. data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -1
  67. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -2
  68. data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -1
  69. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -1
  70. data/lib/contrast/agent/assess/policy/propagator/remove.rb +23 -19
  71. data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -1
  72. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -1
  73. data/lib/contrast/agent/assess/policy/propagator/select.rb +3 -13
  74. data/lib/contrast/agent/assess/policy/propagator/splat.rb +24 -14
  75. data/lib/contrast/agent/assess/policy/propagator/split.rb +18 -15
  76. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +32 -22
  77. data/lib/contrast/agent/assess/policy/propagator/trim.rb +64 -45
  78. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +7 -4
  79. data/lib/contrast/agent/assess/policy/source_method.rb +92 -81
  80. data/lib/contrast/agent/assess/policy/source_node.rb +1 -1
  81. data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +8 -6
  82. data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +2 -4
  83. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -3
  84. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +7 -8
  85. data/lib/contrast/agent/assess/policy/trigger_method.rb +109 -76
  86. data/lib/contrast/agent/assess/policy/trigger_node.rb +33 -11
  87. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +60 -0
  88. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +3 -5
  89. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +7 -5
  90. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +4 -13
  91. data/lib/contrast/agent/assess/properties.rb +1 -3
  92. data/lib/contrast/agent/assess/property/evented.rb +9 -6
  93. data/lib/contrast/agent/assess/property/tagged.rb +38 -20
  94. data/lib/contrast/agent/assess/property/updated.rb +1 -1
  95. data/lib/contrast/agent/assess/rule/provider.rb +1 -1
  96. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +12 -6
  97. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +5 -2
  98. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +4 -6
  99. data/lib/contrast/agent/assess/tag.rb +1 -1
  100. data/lib/contrast/agent/assess/tracker.rb +2 -2
  101. data/lib/contrast/agent/at_exit_hook.rb +1 -1
  102. data/lib/contrast/agent/class_reopener.rb +4 -2
  103. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +1 -1
  104. data/lib/contrast/agent/deadzone/policy/policy.rb +7 -3
  105. data/lib/contrast/agent/disable_reaction.rb +2 -4
  106. data/lib/contrast/agent/exclusion_matcher.rb +6 -12
  107. data/lib/contrast/agent/inventory.rb +1 -2
  108. data/lib/contrast/agent/inventory/dependencies.rb +3 -1
  109. data/lib/contrast/agent/inventory/dependency_analysis.rb +1 -1
  110. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +35 -23
  111. data/lib/contrast/agent/inventory/policy/datastores.rb +1 -1
  112. data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
  113. data/lib/contrast/agent/inventory/policy/trigger_node.rb +1 -1
  114. data/lib/contrast/agent/middleware.rb +111 -110
  115. data/lib/contrast/agent/module_data.rb +4 -4
  116. data/lib/contrast/agent/patching/policy/after_load_patch.rb +1 -1
  117. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +9 -4
  118. data/lib/contrast/agent/patching/policy/method_policy.rb +7 -3
  119. data/lib/contrast/agent/patching/policy/module_policy.rb +15 -8
  120. data/lib/contrast/agent/patching/policy/patch.rb +23 -29
  121. data/lib/contrast/agent/patching/policy/patch_status.rb +8 -9
  122. data/lib/contrast/agent/patching/policy/patcher.rb +72 -64
  123. data/lib/contrast/agent/patching/policy/policy.rb +14 -21
  124. data/lib/contrast/agent/patching/policy/policy_node.rb +15 -5
  125. data/lib/contrast/agent/patching/policy/trigger_node.rb +26 -10
  126. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +2 -2
  127. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +2 -2
  128. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -2
  129. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +3 -4
  130. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +2 -2
  131. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +6 -10
  132. data/lib/contrast/agent/protect/policy/policy.rb +1 -1
  133. data/lib/contrast/agent/protect/policy/rule_applicator.rb +6 -6
  134. data/lib/contrast/agent/protect/policy/trigger_node.rb +1 -1
  135. data/lib/contrast/agent/protect/rule.rb +1 -1
  136. data/lib/contrast/agent/protect/rule/base.rb +19 -33
  137. data/lib/contrast/agent/protect/rule/base_service.rb +10 -6
  138. data/lib/contrast/agent/protect/rule/cmd_injection.rb +15 -19
  139. data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
  140. data/lib/contrast/agent/protect/rule/deserialization.rb +7 -14
  141. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +4 -15
  142. data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -3
  143. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +2 -4
  144. data/lib/contrast/agent/protect/rule/path_traversal.rb +6 -6
  145. data/lib/contrast/agent/protect/rule/sqli.rb +19 -13
  146. data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +1 -1
  147. data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +1 -1
  148. data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +2 -2
  149. data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +1 -1
  150. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +2 -2
  151. data/lib/contrast/agent/protect/rule/xss.rb +2 -2
  152. data/lib/contrast/agent/protect/rule/xxe.rb +6 -13
  153. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +2 -3
  154. data/lib/contrast/agent/railtie.rb +1 -1
  155. data/lib/contrast/agent/reaction_processor.rb +12 -11
  156. data/lib/contrast/agent/request.rb +25 -24
  157. data/lib/contrast/agent/request_context.rb +25 -23
  158. data/lib/contrast/agent/request_handler.rb +1 -1
  159. data/lib/contrast/agent/response.rb +1 -1
  160. data/lib/contrast/agent/rewriter.rb +6 -4
  161. data/lib/contrast/agent/rule_set.rb +3 -3
  162. data/lib/contrast/agent/scope.rb +1 -1
  163. data/lib/contrast/agent/service_heartbeat.rb +3 -4
  164. data/lib/contrast/agent/static_analysis.rb +1 -1
  165. data/lib/contrast/agent/thread.rb +2 -2
  166. data/lib/contrast/agent/thread_watcher.rb +21 -6
  167. data/lib/contrast/agent/tracepoint_hook.rb +2 -2
  168. data/lib/contrast/agent/version.rb +2 -2
  169. data/lib/contrast/agent/worker_thread.rb +1 -1
  170. data/lib/contrast/api.rb +1 -1
  171. data/lib/contrast/api/communication.rb +1 -1
  172. data/lib/contrast/api/communication/connection_status.rb +1 -1
  173. data/lib/contrast/api/communication/messaging_queue.rb +19 -22
  174. data/lib/contrast/api/communication/response_processor.rb +13 -8
  175. data/lib/contrast/api/communication/service_lifecycle.rb +5 -3
  176. data/lib/contrast/api/communication/socket.rb +1 -1
  177. data/lib/contrast/api/communication/socket_client.rb +30 -35
  178. data/lib/contrast/api/communication/speedracer.rb +6 -10
  179. data/lib/contrast/api/communication/tcp_socket.rb +1 -1
  180. data/lib/contrast/api/communication/unix_socket.rb +1 -1
  181. data/lib/contrast/api/decorators.rb +3 -1
  182. data/lib/contrast/api/decorators/address.rb +1 -1
  183. data/lib/contrast/api/decorators/agent_startup.rb +58 -0
  184. data/lib/contrast/api/decorators/application_settings.rb +1 -1
  185. data/lib/contrast/api/decorators/application_startup.rb +57 -0
  186. data/lib/contrast/api/decorators/application_update.rb +1 -1
  187. data/lib/contrast/api/decorators/http_request.rb +1 -1
  188. data/lib/contrast/api/decorators/input_analysis.rb +1 -1
  189. data/lib/contrast/api/decorators/instrumentation_mode.rb +37 -0
  190. data/lib/contrast/api/decorators/library.rb +9 -7
  191. data/lib/contrast/api/decorators/library_usage_update.rb +1 -1
  192. data/lib/contrast/api/decorators/message.rb +4 -4
  193. data/lib/contrast/api/decorators/rasp_rule_sample.rb +1 -1
  194. data/lib/contrast/api/decorators/route_coverage.rb +16 -6
  195. data/lib/contrast/api/decorators/server_features.rb +1 -1
  196. data/lib/contrast/api/decorators/trace_event.rb +46 -16
  197. data/lib/contrast/api/decorators/trace_event_object.rb +2 -4
  198. data/lib/contrast/api/decorators/trace_event_signature.rb +1 -1
  199. data/lib/contrast/api/decorators/trace_taint_range.rb +1 -1
  200. data/lib/contrast/api/decorators/trace_taint_range_tags.rb +2 -7
  201. data/lib/contrast/api/decorators/user_input.rb +1 -1
  202. data/lib/contrast/components/agent.rb +16 -15
  203. data/lib/contrast/components/app_context.rb +11 -29
  204. data/lib/contrast/components/assess.rb +6 -11
  205. data/lib/contrast/components/config.rb +3 -2
  206. data/lib/contrast/components/contrast_service.rb +8 -9
  207. data/lib/contrast/components/heap_dump.rb +1 -1
  208. data/lib/contrast/components/interface.rb +4 -3
  209. data/lib/contrast/components/inventory.rb +1 -1
  210. data/lib/contrast/components/logger.rb +1 -1
  211. data/lib/contrast/components/protect.rb +11 -14
  212. data/lib/contrast/components/sampling.rb +55 -7
  213. data/lib/contrast/components/scope.rb +2 -1
  214. data/lib/contrast/components/settings.rb +29 -99
  215. data/lib/contrast/config.rb +1 -1
  216. data/lib/contrast/config/agent_configuration.rb +1 -1
  217. data/lib/contrast/config/application_configuration.rb +1 -1
  218. data/lib/contrast/config/assess_configuration.rb +1 -1
  219. data/lib/contrast/config/assess_rules_configuration.rb +2 -4
  220. data/lib/contrast/config/base_configuration.rb +5 -6
  221. data/lib/contrast/config/default_value.rb +1 -1
  222. data/lib/contrast/config/exception_configuration.rb +2 -6
  223. data/lib/contrast/config/heap_dump_configuration.rb +13 -7
  224. data/lib/contrast/config/inventory_configuration.rb +1 -1
  225. data/lib/contrast/config/logger_configuration.rb +2 -6
  226. data/lib/contrast/config/protect_configuration.rb +1 -1
  227. data/lib/contrast/config/protect_rule_configuration.rb +23 -1
  228. data/lib/contrast/config/protect_rules_configuration.rb +1 -1
  229. data/lib/contrast/config/root_configuration.rb +1 -1
  230. data/lib/contrast/config/ruby_configuration.rb +1 -1
  231. data/lib/contrast/config/sampling_configuration.rb +1 -1
  232. data/lib/contrast/config/server_configuration.rb +1 -1
  233. data/lib/contrast/config/service_configuration.rb +1 -1
  234. data/lib/contrast/configuration.rb +4 -15
  235. data/lib/contrast/delegators/input_analysis.rb +12 -0
  236. data/lib/contrast/extension/assess.rb +1 -1
  237. data/lib/contrast/extension/assess/array.rb +2 -7
  238. data/lib/contrast/extension/assess/erb.rb +2 -8
  239. data/lib/contrast/extension/assess/eval_trigger.rb +3 -11
  240. data/lib/contrast/extension/assess/exec_trigger.rb +4 -14
  241. data/lib/contrast/extension/assess/fiber.rb +3 -13
  242. data/lib/contrast/extension/assess/hash.rb +1 -1
  243. data/lib/contrast/extension/assess/kernel.rb +3 -10
  244. data/lib/contrast/extension/assess/marshal.rb +3 -11
  245. data/lib/contrast/extension/assess/regexp.rb +2 -7
  246. data/lib/contrast/extension/assess/string.rb +4 -2
  247. data/lib/contrast/extension/delegator.rb +1 -1
  248. data/lib/contrast/extension/inventory.rb +1 -1
  249. data/lib/contrast/extension/kernel.rb +5 -3
  250. data/lib/contrast/extension/module.rb +1 -1
  251. data/lib/contrast/extension/protect.rb +1 -1
  252. data/lib/contrast/extension/protect/kernel.rb +1 -1
  253. data/lib/contrast/extension/protect/psych.rb +1 -1
  254. data/lib/contrast/extension/thread.rb +1 -1
  255. data/lib/contrast/framework/base_support.rb +1 -1
  256. data/lib/contrast/framework/manager.rb +14 -17
  257. data/lib/contrast/framework/platform_version.rb +1 -1
  258. data/lib/contrast/framework/rack/patch/session_cookie.rb +6 -19
  259. data/lib/contrast/framework/rack/patch/support.rb +7 -5
  260. data/lib/contrast/framework/rack/support.rb +1 -1
  261. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -1
  262. data/lib/contrast/framework/rails/patch/assess_configuration.rb +8 -3
  263. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +4 -4
  264. data/lib/contrast/framework/rails/patch/support.rb +5 -3
  265. data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +5 -2
  266. data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +3 -1
  267. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +3 -1
  268. data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +3 -1
  269. data/lib/contrast/framework/rails/support.rb +45 -46
  270. data/lib/contrast/framework/sinatra/support.rb +103 -42
  271. data/lib/contrast/funchook/funchook.rb +2 -6
  272. data/lib/contrast/logger/application.rb +13 -10
  273. data/lib/contrast/logger/format.rb +3 -6
  274. data/lib/contrast/logger/log.rb +36 -19
  275. data/lib/contrast/logger/request.rb +2 -3
  276. data/lib/contrast/logger/time.rb +1 -1
  277. data/lib/contrast/security_exception.rb +2 -2
  278. data/lib/contrast/tasks/config.rb +1 -1
  279. data/lib/contrast/tasks/service.rb +6 -2
  280. data/lib/contrast/utils/assess/sampling_util.rb +1 -1
  281. data/lib/contrast/utils/assess/tracking_util.rb +2 -3
  282. data/lib/contrast/utils/class_util.rb +18 -12
  283. data/lib/contrast/utils/duck_utils.rb +1 -1
  284. data/lib/contrast/utils/env_configuration_item.rb +1 -1
  285. data/lib/contrast/utils/hash_digest.rb +16 -24
  286. data/lib/contrast/utils/heap_dump_util.rb +104 -88
  287. data/lib/contrast/utils/invalid_configuration_util.rb +22 -13
  288. data/lib/contrast/utils/inventory_util.rb +1 -1
  289. data/lib/contrast/utils/io_util.rb +2 -2
  290. data/lib/contrast/utils/job_servers_running.rb +10 -5
  291. data/lib/contrast/utils/object_share.rb +1 -1
  292. data/lib/contrast/utils/os.rb +3 -2
  293. data/lib/contrast/utils/preflight_util.rb +1 -1
  294. data/lib/contrast/utils/resource_loader.rb +1 -1
  295. data/lib/contrast/utils/ruby_ast_rewriter.rb +3 -2
  296. data/lib/contrast/utils/sha256_builder.rb +1 -1
  297. data/lib/contrast/utils/stack_trace_utils.rb +1 -1
  298. data/lib/contrast/utils/string_utils.rb +1 -1
  299. data/lib/contrast/utils/tag_util.rb +1 -1
  300. data/lib/contrast/utils/thread_tracker.rb +1 -1
  301. data/lib/contrast/utils/timer.rb +1 -1
  302. data/resources/assess/policy.json +8 -11
  303. data/resources/deadzone/policy.json +7 -17
  304. data/ruby-agent.gemspec +66 -27
  305. data/service_executables/VERSION +1 -1
  306. data/service_executables/linux/contrast-service +0 -0
  307. data/service_executables/mac/contrast-service +0 -0
  308. data/sonar-project.properties +9 -0
  309. metadata +154 -156
  310. data/lib/contrast/agent/assess/rule.rb +0 -18
  311. data/lib/contrast/agent/assess/rule/base.rb +0 -52
  312. data/lib/contrast/agent/assess/rule/redos.rb +0 -67
  313. data/lib/contrast/agent/inventory/gemfile_digest_cache.rb +0 -38
  314. data/lib/contrast/common_agent_configuration.rb +0 -87
  315. data/lib/contrast/framework/sinatra/patch/base.rb +0 -83
  316. data/lib/contrast/framework/sinatra/patch/support.rb +0 -27
  317. data/lib/contrast/utils/prevent_serialization.rb +0 -52
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'logger'
@@ -27,8 +27,7 @@ module Contrast
27
27
  STDOUT_STR = 'STDOUT'
28
28
  STDERR_STR = 'STDERR'
29
29
 
30
- attr_reader :previous_path,
31
- :previous_level
30
+ attr_reader :previous_path, :previous_level
32
31
 
33
32
  def initialize
34
33
  update
@@ -37,28 +36,22 @@ module Contrast
37
36
  # Given new settings from TeamServer, update our logging to use the new
38
37
  # file and level, assuming they weren't set by local configuration.
39
38
  #
40
- # @param log_file [String] the file to which to log
41
- # @param log_level [String] the level at which to log
39
+ # @param log_file [String] the file to which to log, as provided by TeamServer settings
40
+ # @param log_level [String] the level at which to log, as provided by TeamServer settings
42
41
  def update log_file = nil, log_level = nil
43
- config = CONFIG.root.agent.logger
44
-
45
- config_path = config.path&.length.to_i.positive? ? config.path : nil
46
- config_level = config.level&.length&.positive? ? config.level : nil
47
-
48
- # config > settings > default
49
- path = valid_path(config_path || log_file)
50
- level_const = valid_level(config_level || log_level)
42
+ current_path = find_valid_path(log_file)
43
+ current_level_const = find_valid_level(log_level)
51
44
 
52
- path_change = path != previous_path
53
- level_change = level_const != previous_level
45
+ path_change = current_path != previous_path
46
+ level_change = current_level_const != previous_level
54
47
 
55
48
  # don't needlessly recreate logger
56
49
  return if @_logger && !(path_change || level_change)
57
50
 
58
- @previous_path = path
59
- @previous_level = level_const
51
+ @previous_path = current_path
52
+ @previous_level = current_level_const
60
53
 
61
- @_logger = build(path: path, level_const: level_const)
54
+ @_logger = build(path: current_path, level_const: current_level_const)
62
55
  # If we're logging to a new path, then let's start it w/ our helpful
63
56
  # data gathering messages
64
57
  log_update if path_change
@@ -108,6 +101,17 @@ module Contrast
108
101
  logger.extend(Contrast::Logger::Time)
109
102
  end
110
103
 
104
+ # Determine the valid path to which to log, given the precedence of config > settings > default.
105
+ #
106
+ # @param log_file [String, nil] the file to which to log as provided by the settings retrieved from the
107
+ # TeamServer.
108
+ # @return [String] the path to which to log or STDOUT / STDERR if one of those values provided.
109
+ def find_valid_path log_file
110
+ config = CONFIG.root.agent.logger
111
+ config_path = config.path&.length.to_i.positive? ? config.path : nil
112
+ valid_path(config_path || log_file)
113
+ end
114
+
111
115
  def valid_path path
112
116
  path = path.nil? ? Contrast::Utils::ObjectShare::EMPTY_STRING : path
113
117
  return path if path == STDOUT_STR
@@ -119,7 +123,9 @@ module Contrast
119
123
  elsif write_permission?(DEFAULT_NAME)
120
124
  # Log once when the path is invalid. We'll change to this path, so no
121
125
  # need to log again.
122
- puts "[!] Unable to write to '#{ path }'. Writing to default log '#{ DEFAULT_NAME }' instead." if previous_path != DEFAULT_NAME
126
+ if previous_path != DEFAULT_NAME
127
+ puts "[!] Unable to write to '#{ path }'. Writing to default log '#{ DEFAULT_NAME }' instead."
128
+ end
123
129
  DEFAULT_NAME
124
130
  else
125
131
  # Log once when the path is invalid. We'll change to this path, so no
@@ -129,6 +135,17 @@ module Contrast
129
135
  end
130
136
  end
131
137
 
138
+ # Determine the valid level to which to log, given the precedence of config > settings > default.
139
+ #
140
+ # @param log_level [String, nil] the level at which to log as provided by the settings retrieved from the
141
+ # TeamServer.
142
+ # @return [::Ougai::Logging::Severity] the level at which to log
143
+ def find_valid_level log_level
144
+ config = CONFIG.root.agent.logger
145
+ config_level = config.level&.length&.positive? ? config.level : nil
146
+ valid_level(config_level || log_level)
147
+ end
148
+
132
149
  def valid_level level
133
150
  level ||= DEFAULT_LEVEL
134
151
  level = level.upcase
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/components/interface'
@@ -22,8 +22,7 @@ module Contrast
22
22
  def request_end
23
23
  context = Contrast::Agent::REQUEST_TRACKER.current
24
24
  elapsed_time = context ? (Contrast::Utils::Timer.now_ms - context.timer.start_ms) : -1
25
- debug('Ending request analysis',
26
- elapsed_time_ms: elapsed_time)
25
+ debug('Ending request analysis', elapsed_time_ms: elapsed_time)
27
26
  end
28
27
  end
29
28
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Contrast
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Contrast
@@ -8,7 +8,7 @@ module Contrast
8
8
  # to be handled by our customer's applications.
9
9
  class SecurityException < StandardError
10
10
  def initialize rule, message = nil
11
- super(message || "Rule #{ rule.name } threw a security exception")
11
+ super(message || "Rule #{ rule.rule_name } threw a security exception")
12
12
  end
13
13
  end
14
14
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'yaml'
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/components/interface'
@@ -74,7 +74,11 @@ module Contrast
74
74
  sleep(0.05) while Contrast::Utils::OS.running?
75
75
  end
76
76
  watcher.join(1)
77
- puts Contrast::Utils::OS.running? ? 'Contrast Service did not stop.' : 'Contrast Service stopped successfully.'
77
+ if Contrast::Utils::OS.running?
78
+ puts 'Contrast Service did not stop.'
79
+ else
80
+ puts 'Contrast Service stopped successfully.'
81
+ end
78
82
  else
79
83
  puts 'Contrast Service is not already running. No need to stop.'
80
84
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'singleton'
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/agent/assess/tracker'
@@ -53,8 +53,7 @@ module Contrast
53
53
  idx += 1
54
54
  if Contrast::Utils::DuckUtils.iterable_hash?(obj)
55
55
  obj.each_pair do |k, v|
56
- return true if _tracked?(k, idx)
57
- return true if _tracked?(v, idx)
56
+ return true if _tracked?(k, idx) || _tracked?(v, idx)
58
57
  end
59
58
  false
60
59
  elsif Contrast::Utils::DuckUtils.iterable_enumerable?(obj)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/extension/module'
@@ -9,14 +9,6 @@ module Contrast
9
9
  # Utility methods for exploring the complete space of Objects
10
10
  class ClassUtil
11
11
  class << self
12
- # Given a module, return all of its descendants
13
- #
14
- # @param mod [Module] the module whose descendants you want to find.
15
- # @return [Array<Module>] those Modules that inherit from the given.
16
- def descendants mod
17
- ObjectSpace.each_object(mod).to_a
18
- end
19
-
20
12
  # some classes have had things prepended to them, like Marshal in Rails
21
13
  # 5 and higher. Their ActiveSupport::MarshalWithAutoloading will break
22
14
  # our alias patching approach, as will any other prepend on something
@@ -52,7 +44,7 @@ module Contrast
52
44
  # Return a String representing the object invoking this method in the
53
45
  # form expected by our dataflow events.
54
46
  #
55
- # @param object [Object] the entity to convert to a String
47
+ # @param object [Object, nil] the entity to convert to a String
56
48
  # @return [String] the human readable form of the String, as defined by
57
49
  # https://bitbucket.org/contrastsecurity/assess-specifications/src/master/vulnerability/capture-snapshot.md
58
50
  def to_contrast_string object
@@ -63,14 +55,16 @@ module Contrast
63
55
  return cached if cached
64
56
 
65
57
  object.dup
58
+ elsif object.nil?
59
+ Contrast::Utils::ObjectShare::NIL_STRING
66
60
  elsif object.cs__is_a?(Symbol)
67
61
  ":#{ object }"
68
- elsif object.cs__is_a?(Numeric)
69
- object.to_s
70
62
  elsif object.cs__is_a?(Module) || object.cs__is_a?(Class)
71
63
  "#{ object.cs__name }@#{ object.__id__ }"
72
64
  elsif object.cs__is_a?(Regexp)
73
65
  object.source
66
+ elsif use_to_s?(object)
67
+ object.to_s
74
68
  else
75
69
  "#{ object.cs__class.cs__name }@#{ object.__id__ }"
76
70
  end
@@ -106,6 +100,18 @@ module Contrast
106
100
 
107
101
  private
108
102
 
103
+ # Some objects have nice to_s that we can use to make them human readable. If they do, we should leverage them.
104
+ # We used to do this by default, but this opened us up to danger, so we're instead using an allow list approach.
105
+ #
106
+ # @param object [Object] something that may have a safe to_s method
107
+ # @return [Boolean] if we should invoke to_s to represent the object
108
+ def use_to_s? object
109
+ return true if object.cs__is_a?(Numeric)
110
+ return true if defined?(Arel::Nodes::SqlLiteral) && object.cs__is_a?(Arel::Nodes::SqlLiteral)
111
+
112
+ false
113
+ end
114
+
109
115
  def determine_target_class mod, is_instance
110
116
  return mod if mod.singleton_class?
111
117
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Contrast
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Contrast
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'digest'
@@ -15,10 +15,7 @@ module Contrast
15
15
  include Digest::Instance
16
16
 
17
17
  CONTENT_LENGTH_HEADER = 'Content-Length'
18
- CRYPTO_RULES = %w[
19
- crypto-bad-ciphers
20
- crypto-bad-mac
21
- ].cs__freeze
18
+ CRYPTO_RULES = %w[crypto-bad-ciphers crypto-bad-mac].cs__freeze
22
19
  CONFIG_PATH_KEY = 'path'
23
20
  CONFIG_SESSION_ID_KEY = 'sessionId'
24
21
  CLASS_SOURCE_KEY = 'source'
@@ -37,13 +34,13 @@ module Contrast
37
34
  hash.finish
38
35
  end
39
36
 
40
- def generate_event_hash finding, source
41
- return generate_dataflow_hash(finding) if finding.events.length.to_i > 1
37
+ def generate_event_hash finding, source, request
38
+ return generate_dataflow_hash(finding, request) if finding.events.length.to_i > 1
42
39
 
43
40
  id = finding.rule_id
44
- return generate_crypto_hash(finding, source) if CRYPTO_RULES.include?(id)
41
+ return generate_crypto_hash(finding, source, request) if CRYPTO_RULES.include?(id)
45
42
 
46
- generate_trigger_hash(finding)
43
+ generate_trigger_hash(finding, request)
47
44
  end
48
45
 
49
46
  def generate_config_hash finding
@@ -71,40 +68,35 @@ module Contrast
71
68
 
72
69
  private
73
70
 
74
- def generate_crypto_hash finding, algorithm
71
+ def generate_crypto_hash finding, algorithm, request
75
72
  hash = new
76
73
  hash.update(finding.rule_id)
77
74
  hash.update(algorithm)
78
- hash.update_on_request
75
+ hash.update_on_request(finding, request)
79
76
  hash.finish
80
77
  end
81
78
 
82
- def generate_dataflow_hash finding
79
+ def generate_dataflow_hash finding, request
83
80
  hash = new
84
81
  hash.update(finding.rule_id)
85
82
  hash.update_on_sources(finding.events)
86
- hash.update_on_request
83
+ hash.update_on_request(finding, request)
87
84
  hash.finish
88
85
  end
89
86
 
90
- def generate_trigger_hash finding
87
+ def generate_trigger_hash finding, request
91
88
  hash = new
92
89
  hash.update(finding.rule_id)
93
- hash.update_on_request
90
+ hash.update_on_request(finding, request)
94
91
  hash.finish
95
92
  end
96
93
  end
97
94
 
98
- def update_on_request
99
- context = Contrast::Agent::REQUEST_TRACKER.current
100
- return unless context
101
-
102
- route = context.route
103
- request = context.request
104
- if route
95
+ def update_on_request finding, request
96
+ if (route = finding.routes[0])
105
97
  update(route.route)
106
98
  update(route.verb)
107
- elsif request
99
+ elsif request ||= Contrast::Agent::REQUEST_TRACKER.current&.request
108
100
  update(request.normalized_uri)
109
101
  update(request.request_method)
110
102
  end
@@ -116,7 +108,7 @@ module Contrast
116
108
  events.each do |event|
117
109
  event.event_sources.each do |source|
118
110
  update(source.type)
119
- update(source.name)
111
+ update(source.name) # rubocop:disable Security/Module/Name -- API attribute.
120
112
  end
121
113
  end
122
114
  end
@@ -1,13 +1,14 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
1
+ # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'objspace'
5
+ require 'singleton'
5
6
  require 'contrast/components/interface'
6
7
 
7
8
  module Contrast
8
9
  module Utils
9
10
  # Implementation of a heap dump util to automate generation
10
- class HeapDumpUtil
11
+ class HeapDumpUtil < Contrast::Agent::WorkerThread
11
12
  include Contrast::Components::Interface
12
13
  access_component :heap_dump, :logging
13
14
 
@@ -15,98 +16,113 @@ module Contrast
15
16
  FILE_WRITE_FLAGS = 'w'
16
17
 
17
18
  class << self
18
- def run
19
- return unless heap_dump_enabled?
20
-
21
- log_enabled_warning
22
- dir = heap_dump_control[:path]
23
- Dir.mkdir(dir) unless Dir.exist?(dir)
24
- return unless File.writable?(dir)
25
-
26
- delay = heap_dump_control[:delay]
27
- Contrast::Agent::Thread.new do
28
- logger.info("HEAP DUMP THREAD INITIALIZED. WAITING #{ delay } SECONDS TO BEGIN.")
29
- sleep(delay)
30
- capture_heap_dump
31
- end
32
- rescue StandardError => e
33
- logger.info(LOG_ERROR_DUMPS, e)
34
- nil
19
+ def enabled?
20
+ heap_dump_enabled?
21
+ end
22
+
23
+ def control
24
+ heap_dump_control
35
25
  end
26
+ end
27
+
28
+ def start_thread!
29
+ return unless Contrast::Utils::HeapDumpUtil.enabled?
36
30
 
37
- def log_enabled_warning
38
- dir = heap_dump_control[:path]
39
- window = heap_dump_control[:window]
40
- count = heap_dump_control[:count]
41
- delay = heap_dump_control[:delay]
42
- clean = heap_dump_control[:clean]
43
-
44
- logger.info <<~WARNING
45
- *****************************************************
46
- ******** HEAP DUMP HAS BEEN ENABLED ********
47
- *** APPLICATION PROCESS WILL EXIT UPON COMPLETION ***
48
- *****************************************************
49
-
50
- Heap dump is a debugging tool that snapshots the entire
51
- state of the Ruby VM. It is an exceptionally expensive
52
- process, and should only be used to debug especially
53
- pernicious errors.
54
-
55
- It will write multiple memory snaphots, which are liable
56
- to be multiple gigabytes in size.
57
- They will be named "[unix timestamp]-heap.dump",
58
- e.g.: 1020304050-heap.dump
59
-
60
- It will then call Ruby `exit()`.
61
-
62
- If this is not your specific intent, you can (and should)
63
- disable this option in your Contrast config file.
64
-
65
- HEAP DUMP PARAMETERS:
66
- \t[write files to this directory] dir: #{ dir }
67
- \t[wait this many seconds in between dumps] window: #{ window }
68
- \t[heap dump this many times] count: #{ count }
69
- \t[wait this many seconds into app lifetime] delay: #{ delay }
70
- \t[perform gc pass before dump] clean: #{ clean }
71
-
72
- *****************************************************
73
- ******** YOU HAVE BEEN WARNED ********
74
- *****************************************************
75
- WARNING
31
+ control = Contrast::Utils::HeapDumpUtil.control
32
+ log_enabled_warning
33
+ dir = control[:path]
34
+ Dir.mkdir(dir) unless Dir.exist?(dir)
35
+ return unless File.writable?(dir)
36
+
37
+ delay = control[:delay]
38
+ @_thread = Contrast::Agent::Thread.new do
39
+ logger.info("HEAP DUMP THREAD INITIALIZED. WAITING #{ delay } SECONDS TO BEGIN.")
40
+ sleep(delay)
41
+ capture_heap_dump
76
42
  end
43
+ rescue StandardError => e
44
+ logger.info(LOG_ERROR_DUMPS, e)
45
+ nil
46
+ end
47
+
48
+ def log_enabled_warning
49
+ control = Contrast::Utils::HeapDumpUtil.control
50
+ dir = control[:path]
51
+ window = control[:window]
52
+ count = control[:count]
53
+ delay = control[:delay]
54
+ clean = control[:clean]
55
+
56
+ logger.info <<~WARNING
57
+ *****************************************************
58
+ ******** HEAP DUMP HAS BEEN ENABLED ********
59
+ *** APPLICATION PROCESS WILL EXIT UPON COMPLETION ***
60
+ *****************************************************
61
+
62
+ Heap dump is a debugging tool that snapshots the entire
63
+ state of the Ruby VM. It is an exceptionally expensive
64
+ process, and should only be used to debug especially
65
+ pernicious errors.
66
+
67
+ It will write multiple memory snaphots, which are liable
68
+ to be multiple gigabytes in size.
69
+ They will be named "[unix timestamp]-heap.dump",
70
+ e.g.: 1020304050-heap.dump
71
+
72
+ It will then call Ruby `exit()`.
73
+
74
+ If this is not your specific intent, you can (and should)
75
+ disable this option in your Contrast config file.
76
+
77
+ HEAP DUMP PARAMETERS:
78
+ \t[write files to this directory] dir: #{ dir }
79
+ \t[wait this many seconds in between dumps] window: #{ window }
80
+ \t[heap dump this many times] count: #{ count }
81
+ \t[wait this many seconds into app lifetime] delay: #{ delay }
82
+ \t[perform gc pass before dump] clean: #{ clean }
83
+
84
+ *****************************************************
85
+ ******** YOU HAVE BEEN WARNED ********
86
+ *****************************************************
87
+ WARNING
88
+ end
89
+
90
+ def capture_heap_dump
91
+ control = Contrast::Utils::HeapDumpUtil.control
92
+ dir = control[:path]
93
+ window = control[:window]
94
+ count = control[:count]
95
+ clean = control[:clean]
96
+ logger.info('HEAP DUMP MAIN LOOP')
97
+ ObjectSpace.trace_object_allocations_start
98
+ count.times do |i|
99
+ logger.info('STARTING HEAP DUMP PASS', current_pass: i, max: count)
100
+ snapshot_heap(dir, clean)
101
+ logger.info('FINISHING HEAP DUMP PASS', current_pass: i, max: count)
102
+ sleep(window)
103
+ end
104
+ ensure
105
+ ObjectSpace.trace_object_allocations_stop
106
+ logger.info('*****************************************************')
107
+ logger.info('******** HEAP DUMP HAS CONCLUDED ********')
108
+ logger.info('*** APPLICATION PROCESS WILL EXIT SHORTLY ***')
109
+ logger.info('*****************************************************')
110
+ exit # rubocop:disable Rails/Exit We weren't kidding!
111
+ end
77
112
 
78
- def capture_heap_dump
79
- dir = heap_dump_control[:path]
80
- window = heap_dump_control[:window]
81
- count = heap_dump_control[:count]
82
- clean = heap_dump_control[:clean]
83
- logger.info('HEAP DUMP MAIN LOOP')
84
- ObjectSpace.trace_object_allocations_start
85
- count.times do |i|
86
- logger.info('STARTING HEAP DUMP PASS', current_pass: i + 1, max: count)
87
- output = "#{ Time.now.to_f }-heap.dump"
88
- output = File.join(dir, output)
89
- begin
90
- logger.info('OPENING HEADUMP FILE', dir: dir, file: output)
91
- file = File.new(output, FILE_WRITE_FLAGS)
92
- if clean
93
- logger.info('PERFORMING GARBAGE COLLECTION BEFORE HEAP DUMP')
94
- GC.start
95
- end
96
- ObjectSpace.dump_all(output: file)
97
- logger.info('FINISHING HEAP DUMP PASS', current_pass: i + 1, max: count)
98
- ensure
99
- file.close
100
- end
101
- sleep(window)
113
+ def snapshot_heap dir, clean
114
+ output = "#{ Time.now.to_f }-heap.dump"
115
+ output = File.join(dir, output)
116
+ begin
117
+ logger.info('OPENING HEADUMP FILE', dir: dir, file: output)
118
+ file = File.new(output, FILE_WRITE_FLAGS)
119
+ if clean
120
+ logger.info('PERFORMING GARBAGE COLLECTION BEFORE HEAP DUMP')
121
+ GC.start
102
122
  end
123
+ ObjectSpace.dump_all(output: file)
103
124
  ensure
104
- ObjectSpace.trace_object_allocations_stop
105
- logger.info('*****************************************************')
106
- logger.info('******** HEAP DUMP HAS CONCLUDED ********')
107
- logger.info('*** APPLICATION PROCESS WILL EXIT SHORTLY ***')
108
- logger.info('*****************************************************')
109
- exit # rubocop:disable Rails/Exit We weren't kidding!
125
+ file.close
110
126
  end
111
127
  end
112
128
  end