contrast-agent 6.7.0 → 6.9.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 (280) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.simplecov +0 -1
  4. data/Rakefile +0 -1
  5. data/ext/cs__assess_array/cs__assess_array.c +41 -10
  6. data/ext/cs__assess_array/cs__assess_array.h +4 -1
  7. data/lib/contrast/agent/assess/policy/trigger_method.rb +3 -3
  8. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +1 -1
  9. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
  10. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -1
  11. data/lib/contrast/agent/assess/property/evented.rb +11 -11
  12. data/lib/contrast/agent/assess.rb +0 -1
  13. data/lib/contrast/agent/excluder.rb +53 -35
  14. data/lib/contrast/agent/exclusion_matcher.rb +21 -9
  15. data/lib/contrast/agent/middleware.rb +12 -6
  16. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +6 -0
  17. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +146 -127
  18. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +116 -0
  19. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +20 -0
  20. data/lib/contrast/agent/protect/policy/rule_applicator.rb +1 -1
  21. data/lib/contrast/agent/protect/rule/base.rb +47 -55
  22. data/lib/contrast/agent/protect/rule/base_service.rb +48 -24
  23. data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +98 -0
  24. data/lib/contrast/agent/protect/rule/bot_blocker.rb +81 -0
  25. data/lib/contrast/agent/protect/rule/cmd_injection.rb +20 -2
  26. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +8 -5
  27. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +22 -22
  28. data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +64 -0
  29. data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +63 -0
  30. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +2 -58
  31. data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
  32. data/lib/contrast/agent/protect/rule/deserialization.rb +3 -14
  33. data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +2 -2
  34. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +0 -11
  35. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +29 -34
  36. data/lib/contrast/agent/protect/rule/no_sqli.rb +25 -18
  37. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_input_classification.rb +61 -0
  38. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +114 -0
  39. data/lib/contrast/agent/protect/rule/path_traversal.rb +40 -13
  40. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +33 -15
  41. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +0 -14
  42. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +2 -62
  43. data/lib/contrast/agent/protect/rule/sqli.rb +74 -3
  44. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +39 -63
  45. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +6 -33
  46. data/lib/contrast/agent/protect/rule/xss/reflected_xss_input_classification.rb +58 -0
  47. data/lib/contrast/agent/protect/rule/xss.rb +15 -20
  48. data/lib/contrast/agent/protect/rule/xxe.rb +4 -24
  49. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +19 -40
  50. data/lib/contrast/agent/reporting/attack_result/response_type.rb +9 -9
  51. data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +10 -2
  52. data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +8 -2
  53. data/lib/contrast/agent/reporting/input_analysis/details/bot_blocker_details.rb +27 -0
  54. data/lib/contrast/agent/reporting/input_analysis/details/protect_rule_details.rb +15 -0
  55. data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +1 -2
  56. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +16 -2
  57. data/lib/contrast/agent/reporting/masker/masker.rb +2 -0
  58. data/lib/contrast/agent/reporting/report.rb +1 -0
  59. data/lib/contrast/agent/reporting/reporter.rb +35 -14
  60. data/lib/contrast/agent/reporting/reporter_heartbeat.rb +3 -9
  61. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +16 -13
  62. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +12 -7
  63. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +3 -3
  64. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +1 -2
  65. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -1
  66. data/lib/contrast/agent/reporting/reporting_events/application_update.rb +0 -2
  67. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +0 -1
  68. data/lib/contrast/agent/reporting/reporting_events/finding.rb +6 -6
  69. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +239 -93
  70. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -23
  71. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +10 -9
  72. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +0 -5
  73. data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +0 -1
  74. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +12 -0
  75. data/lib/contrast/agent/reporting/reporting_events/poll.rb +1 -11
  76. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +0 -1
  77. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +0 -1
  78. data/lib/contrast/agent/reporting/reporting_events/server_reporting_event.rb +8 -0
  79. data/lib/contrast/agent/reporting/reporting_events/server_settings.rb +40 -0
  80. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +2 -2
  81. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +6 -0
  82. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +43 -1
  83. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +8 -4
  84. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +1 -1
  85. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +58 -4
  86. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +4 -6
  87. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +77 -16
  88. data/lib/contrast/agent/reporting/server_settings_worker.rb +44 -0
  89. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +14 -2
  90. data/lib/contrast/agent/reporting/settings/code_exclusion.rb +6 -1
  91. data/lib/contrast/agent/reporting/settings/exclusion_base.rb +18 -0
  92. data/lib/contrast/agent/reporting/settings/exclusions.rb +2 -1
  93. data/lib/contrast/agent/reporting/settings/helpers.rb +7 -0
  94. data/lib/contrast/agent/reporting/settings/input_exclusion.rb +9 -3
  95. data/lib/contrast/agent/reporting/settings/protect.rb +15 -15
  96. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +39 -2
  97. data/lib/contrast/agent/reporting/settings/rule_definition.rb +3 -0
  98. data/lib/contrast/agent/reporting/settings/security_logger.rb +77 -0
  99. data/lib/contrast/agent/reporting/settings/server_features.rb +9 -0
  100. data/lib/contrast/agent/reporting/settings/syslog.rb +34 -5
  101. data/lib/contrast/agent/request.rb +3 -14
  102. data/lib/contrast/agent/request_context.rb +6 -9
  103. data/lib/contrast/agent/request_context_extend.rb +9 -148
  104. data/lib/contrast/agent/request_handler.rb +5 -10
  105. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +1 -1
  106. data/lib/contrast/agent/thread_watcher.rb +37 -18
  107. data/lib/contrast/agent/version.rb +1 -1
  108. data/lib/contrast/agent.rb +6 -11
  109. data/lib/contrast/agent_lib/api/command_injection.rb +46 -0
  110. data/lib/contrast/agent_lib/api/init.rb +101 -0
  111. data/lib/contrast/agent_lib/api/input_tracing.rb +267 -0
  112. data/lib/contrast/agent_lib/api/method_tempering.rb +29 -0
  113. data/lib/contrast/agent_lib/api/panic.rb +87 -0
  114. data/lib/contrast/agent_lib/api/path_semantic_file_security_bypass.rb +40 -0
  115. data/lib/contrast/agent_lib/interface.rb +260 -0
  116. data/lib/contrast/agent_lib/interface_base.rb +118 -0
  117. data/lib/contrast/agent_lib/return_types/eval_result.rb +44 -0
  118. data/lib/contrast/agent_lib/test.rb +29 -0
  119. data/lib/contrast/api/communication/connection_status.rb +20 -5
  120. data/lib/contrast/components/agent.rb +34 -14
  121. data/lib/contrast/components/api.rb +23 -0
  122. data/lib/contrast/components/app_context.rb +23 -5
  123. data/lib/contrast/components/app_context_extend.rb +0 -25
  124. data/lib/contrast/components/assess.rb +34 -4
  125. data/lib/contrast/components/assess_rules.rb +18 -0
  126. data/lib/contrast/components/base.rb +40 -0
  127. data/lib/contrast/components/config/sources.rb +95 -0
  128. data/lib/contrast/components/config.rb +19 -19
  129. data/lib/contrast/components/heap_dump.rb +10 -0
  130. data/lib/contrast/components/inventory.rb +15 -2
  131. data/lib/contrast/components/logger.rb +18 -0
  132. data/lib/contrast/components/polling.rb +36 -0
  133. data/lib/contrast/components/protect.rb +52 -2
  134. data/lib/contrast/components/ruby_component.rb +16 -1
  135. data/lib/contrast/components/sampling.rb +70 -13
  136. data/lib/contrast/components/security_logger.rb +13 -0
  137. data/lib/contrast/components/settings.rb +105 -90
  138. data/lib/contrast/config/certification_configuration.rb +14 -0
  139. data/lib/contrast/config/config.rb +46 -0
  140. data/lib/contrast/config/diagnostics.rb +114 -0
  141. data/lib/contrast/config/diagnostics_tools.rb +98 -0
  142. data/lib/contrast/config/effective_config.rb +65 -0
  143. data/lib/contrast/config/effective_config_value.rb +32 -0
  144. data/lib/contrast/config/exception_configuration.rb +12 -0
  145. data/lib/contrast/config/protect_rule_configuration.rb +8 -8
  146. data/lib/contrast/config/protect_rules_configuration.rb +23 -60
  147. data/lib/contrast/config/request_audit_configuration.rb +13 -0
  148. data/lib/contrast/config/server_configuration.rb +41 -2
  149. data/lib/contrast/configuration.rb +29 -12
  150. data/lib/contrast/extension/assess/array.rb +9 -0
  151. data/lib/contrast/extension/assess/erb.rb +1 -1
  152. data/lib/contrast/extension/delegator.rb +2 -0
  153. data/lib/contrast/framework/manager.rb +3 -1
  154. data/lib/contrast/framework/rails/railtie.rb +0 -1
  155. data/lib/contrast/framework/rails/support.rb +0 -1
  156. data/lib/contrast/tasks/config.rb +1 -8
  157. data/lib/contrast/utils/assess/event_limit_utils.rb +31 -9
  158. data/lib/contrast/utils/assess/trigger_method_utils.rb +5 -4
  159. data/lib/contrast/utils/duck_utils.rb +1 -0
  160. data/lib/contrast/utils/hash_digest.rb +2 -2
  161. data/lib/contrast/utils/input_classification_base.rb +155 -0
  162. data/lib/contrast/utils/os.rb +0 -20
  163. data/lib/contrast/utils/reporting/application_activity_batch_utils.rb +81 -0
  164. data/lib/contrast/utils/response_utils.rb +0 -16
  165. data/lib/contrast/utils/routes_sent.rb +60 -0
  166. data/lib/contrast/utils/stack_trace_utils.rb +3 -15
  167. data/lib/contrast/utils/string_utils.rb +10 -7
  168. data/lib/contrast/utils/telemetry_client.rb +1 -2
  169. data/lib/contrast/utils/timer.rb +16 -0
  170. data/lib/contrast.rb +5 -4
  171. data/resources/protect/policy.json +1 -2
  172. data/ruby-agent.gemspec +7 -6
  173. metadata +69 -130
  174. data/exe/contrast_service +0 -23
  175. data/lib/contrast/agent/assess/contrast_event.rb +0 -157
  176. data/lib/contrast/agent/assess/events/event_factory.rb +0 -34
  177. data/lib/contrast/agent/assess/events/source_event.rb +0 -46
  178. data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +0 -64
  179. data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +0 -118
  180. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +0 -45
  181. data/lib/contrast/agent/reaction_processor.rb +0 -47
  182. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -36
  183. data/lib/contrast/agent/service_heartbeat.rb +0 -35
  184. data/lib/contrast/api/communication/messaging_queue.rb +0 -128
  185. data/lib/contrast/api/communication/response_processor.rb +0 -90
  186. data/lib/contrast/api/communication/service_lifecycle.rb +0 -77
  187. data/lib/contrast/api/communication/socket.rb +0 -44
  188. data/lib/contrast/api/communication/socket_client.rb +0 -130
  189. data/lib/contrast/api/communication/speedracer.rb +0 -138
  190. data/lib/contrast/api/communication/tcp_socket.rb +0 -32
  191. data/lib/contrast/api/communication/unix_socket.rb +0 -28
  192. data/lib/contrast/api/communication.rb +0 -20
  193. data/lib/contrast/api/decorators/address.rb +0 -59
  194. data/lib/contrast/api/decorators/agent_startup.rb +0 -56
  195. data/lib/contrast/api/decorators/application_settings.rb +0 -43
  196. data/lib/contrast/api/decorators/application_startup.rb +0 -56
  197. data/lib/contrast/api/decorators/bot_blocker.rb +0 -37
  198. data/lib/contrast/api/decorators/http_request.rb +0 -137
  199. data/lib/contrast/api/decorators/input_analysis.rb +0 -18
  200. data/lib/contrast/api/decorators/instrumentation_mode.rb +0 -35
  201. data/lib/contrast/api/decorators/ip_denylist.rb +0 -37
  202. data/lib/contrast/api/decorators/message.rb +0 -67
  203. data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -52
  204. data/lib/contrast/api/decorators/response_type.rb +0 -17
  205. data/lib/contrast/api/decorators/server_features.rb +0 -25
  206. data/lib/contrast/api/decorators/user_input.rb +0 -51
  207. data/lib/contrast/api/decorators/virtual_patch.rb +0 -34
  208. data/lib/contrast/api/decorators.rb +0 -22
  209. data/lib/contrast/api/dtm.pb.rb +0 -363
  210. data/lib/contrast/api/settings.pb.rb +0 -500
  211. data/lib/contrast/api.rb +0 -16
  212. data/lib/contrast/components/contrast_service.rb +0 -88
  213. data/lib/contrast/components/service.rb +0 -55
  214. data/lib/contrast/tasks/service.rb +0 -84
  215. data/lib/contrast/utils/input_classification.rb +0 -73
  216. data/lib/protobuf/code_generator.rb +0 -129
  217. data/lib/protobuf/decoder.rb +0 -28
  218. data/lib/protobuf/deprecation.rb +0 -117
  219. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +0 -79
  220. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +0 -360
  221. data/lib/protobuf/descriptors.rb +0 -3
  222. data/lib/protobuf/encoder.rb +0 -11
  223. data/lib/protobuf/enum.rb +0 -365
  224. data/lib/protobuf/exceptions.rb +0 -9
  225. data/lib/protobuf/field/base_field.rb +0 -380
  226. data/lib/protobuf/field/base_field_object_definitions.rb +0 -504
  227. data/lib/protobuf/field/bool_field.rb +0 -64
  228. data/lib/protobuf/field/bytes_field.rb +0 -67
  229. data/lib/protobuf/field/double_field.rb +0 -25
  230. data/lib/protobuf/field/enum_field.rb +0 -56
  231. data/lib/protobuf/field/field_array.rb +0 -102
  232. data/lib/protobuf/field/field_hash.rb +0 -122
  233. data/lib/protobuf/field/fixed32_field.rb +0 -25
  234. data/lib/protobuf/field/fixed64_field.rb +0 -28
  235. data/lib/protobuf/field/float_field.rb +0 -43
  236. data/lib/protobuf/field/int32_field.rb +0 -21
  237. data/lib/protobuf/field/int64_field.rb +0 -34
  238. data/lib/protobuf/field/integer_field.rb +0 -23
  239. data/lib/protobuf/field/message_field.rb +0 -51
  240. data/lib/protobuf/field/sfixed32_field.rb +0 -27
  241. data/lib/protobuf/field/sfixed64_field.rb +0 -28
  242. data/lib/protobuf/field/signed_integer_field.rb +0 -29
  243. data/lib/protobuf/field/sint32_field.rb +0 -21
  244. data/lib/protobuf/field/sint64_field.rb +0 -21
  245. data/lib/protobuf/field/string_field.rb +0 -51
  246. data/lib/protobuf/field/uint32_field.rb +0 -21
  247. data/lib/protobuf/field/uint64_field.rb +0 -21
  248. data/lib/protobuf/field/varint_field.rb +0 -77
  249. data/lib/protobuf/field.rb +0 -74
  250. data/lib/protobuf/generators/base.rb +0 -85
  251. data/lib/protobuf/generators/enum_generator.rb +0 -39
  252. data/lib/protobuf/generators/extension_generator.rb +0 -27
  253. data/lib/protobuf/generators/field_generator.rb +0 -193
  254. data/lib/protobuf/generators/file_generator.rb +0 -262
  255. data/lib/protobuf/generators/group_generator.rb +0 -122
  256. data/lib/protobuf/generators/message_generator.rb +0 -104
  257. data/lib/protobuf/generators/option_generator.rb +0 -17
  258. data/lib/protobuf/generators/printable.rb +0 -160
  259. data/lib/protobuf/generators/service_generator.rb +0 -50
  260. data/lib/protobuf/lifecycle.rb +0 -33
  261. data/lib/protobuf/logging.rb +0 -39
  262. data/lib/protobuf/message/fields.rb +0 -233
  263. data/lib/protobuf/message/serialization.rb +0 -85
  264. data/lib/protobuf/message.rb +0 -241
  265. data/lib/protobuf/optionable.rb +0 -72
  266. data/lib/protobuf/tasks/compile.rake +0 -80
  267. data/lib/protobuf/tasks.rb +0 -1
  268. data/lib/protobuf/varint.rb +0 -20
  269. data/lib/protobuf/varint_pure.rb +0 -31
  270. data/lib/protobuf/version.rb +0 -3
  271. data/lib/protobuf/wire_type.rb +0 -10
  272. data/lib/protobuf.rb +0 -91
  273. data/proto/dynamic_discovery.proto +0 -46
  274. data/proto/google/protobuf/compiler/plugin.proto +0 -183
  275. data/proto/google/protobuf/descriptor.proto +0 -911
  276. data/proto/rpc.proto +0 -71
  277. data/service_executables/.gitkeep +0 -0
  278. data/service_executables/VERSION +0 -1
  279. data/service_executables/linux/contrast-service +0 -0
  280. data/service_executables/mac/contrast-service +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c688788c7666c5ea72351e52ad02fe838923dc0dde589199917d2bfa96080630
4
- data.tar.gz: f63416e47b9b815f0ec7a79858fb11f866bf5c49c952cf278dfb851679f44957
3
+ metadata.gz: b850f63bce180f09f998f5363f58b01e9c69db61a2f98a31db97fb59b82564d7
4
+ data.tar.gz: 811072666998fb4daf0f49d2514d875b45c18d79d29398639862f1c2144aa930
5
5
  SHA512:
6
- metadata.gz: 0b5ee56bb30a55609a6252a105c8ab60e0bf66bdcac23e4efa937cfbc99f7669ab5ed7ffdc41dfd1b9659a09a93d2f7714af0eb398b46069542f0dff753c1ccd
7
- data.tar.gz: 84b72b0f516808677745cc1ea7ecdedf762309ceb79eaac2908f1f16ac6abc811f2997bc50673e78101d7845ddd67a73c996c7ed3ebdbca6d33cf88883926499
6
+ metadata.gz: ac0f4dcea0a62d6aa000659943f2b994a02940148fffdff2901ff4ff61d27fd257170ec4f48d0b1925d569dbc20de89a8866f76a17dd1c22aa15d9c80e4e9eb1
7
+ data.tar.gz: bd2490f015d1a5c8be5f0e7a0fc60e5acdc436b03e32420cbf19542a53b760c843cd84a17a0e7a8a3794ec69e3aa909e63fabdb32f4c32d5daa48ece261176aa
data/.gitignore CHANGED
@@ -21,7 +21,6 @@
21
21
  bin
22
22
  ruby-spec
23
23
  mspec
24
- service_executables
25
24
 
26
25
  # rspec generated files
27
26
  /spec/dummy_files/*
@@ -57,7 +56,6 @@ contrast-agent-*.gem
57
56
 
58
57
  .ruby-version
59
58
  .ruby-gemset
60
- service_executables/*-*
61
59
 
62
60
  # IDE stuff
63
61
  tags
data/.simplecov CHANGED
@@ -4,6 +4,5 @@
4
4
  SimpleCov.minimum_coverage(line: 94)
5
5
  SimpleCov.start do
6
6
  add_filter '/spec/'
7
- add_filter '/lib/protobuf/'
8
7
  enable_coverage :branch
9
8
  end
data/Rakefile CHANGED
@@ -6,7 +6,6 @@ $stdout.sync = true
6
6
  require 'bundler/gem_tasks'
7
7
  require 'rspec/core/rake_task'
8
8
  require 'rake/extensiontask'
9
- load 'protobuf/tasks/compile.rake'
10
9
  require 'fileutils'
11
10
 
12
11
  CLOBBER << 'shared_libraries/*'
@@ -31,15 +31,46 @@ static VALUE contrast_assess_array_join(const int argc, const VALUE *argv,
31
31
  return result;
32
32
  }
33
33
 
34
+ static VALUE contrast_assess_prepend_array_join(const int argc, const VALUE *argv,
35
+ const VALUE ary) {
36
+ VALUE sep, result;
37
+ /* We need to figure out the separator the join method actually used. */
38
+ /* First, check if one was provided. */
39
+ rb_scan_args(argc, argv, "01", &sep);
40
+ /* Second, check to see if `$;` is set*/
41
+ if (NIL_P(sep)) {
42
+ sep = rb_output_fs;
43
+ }
44
+
45
+ /* call the Array.join but patched one */
46
+ result = rb_ary_join(ary, sep);
47
+ /* call the Contrast::Extensions::Assess::ArrayPropagator#cs__track_join */
48
+ result = rb_funcall(array_propagator, rb_sym_assess_track_array_join, 3,
49
+ ary, sep, result);
50
+
51
+ /*call original occurs in ruby*/
52
+ return Qtrue;
53
+ }
54
+
34
55
  void Init_cs__assess_array(void) {
35
- array_propagator =
36
- rb_define_class_under(core_assess, "ArrayPropagator", rb_cObject);
37
- rb_sym_assess_track_array_join = rb_intern("cs__track_join");
38
- /*
39
- * Here we need to check before using the alias or prepend spec
40
- * This patch is happening here, we register the cs__track_join
41
- * method of the Array propagator, and call it here from Ruby.
42
- */
43
- rb_sym_assess_array_join =
44
- contrast_register_patch("Array", "join", contrast_assess_array_join);
56
+
57
+ VALUE rb_mod_ary = rb_const_get(rb_cObject, rb_intern("Array"));
58
+ VALUE rb_sym_ary_join = ID2SYM(rb_intern("join"));
59
+ // check if prepended
60
+ VALUE is_prepended = contrast_check_prepended(rb_mod_ary, rb_sym_ary_join, Qtrue);
61
+ // register the cs__track_join method of the Array propagator, and call it here from Ruby.
62
+ array_propagator = rb_define_class_under(core_assess, "ArrayPropagator", rb_cObject);
63
+ rb_sym_assess_track_array_join = rb_intern("cs__track_join");
64
+
65
+ // register the cs__join method of the ContrastArray for prepending, and call it here from Ruby.
66
+ VALUE contrast_array = rb_define_module_under(core_assess, "ContrastArray");
67
+ rb_define_module_function(contrast_array, "cs__join", contrast_assess_prepend_array_join, -1);
68
+
69
+ if(is_prepended == Qtrue) {
70
+ // do nothing prepend is done in Ruby
71
+ } else {
72
+ // register alias patch
73
+ rb_sym_assess_array_join =
74
+ contrast_register_patch("Array", "join", contrast_assess_array_join);
75
+ }
45
76
  }
@@ -3,8 +3,11 @@
3
3
  static VALUE array_propagator;
4
4
  static VALUE rb_sym_assess_array_join;
5
5
  static VALUE rb_sym_assess_track_array_join;
6
-
6
+ static VALUE rb_mod_ary, rb_sym_ary_join, is_prepended, contrast_array;
7
7
  static VALUE contrast_assess_array_join(const int argc, const VALUE *argv,
8
8
  const VALUE ary);
9
9
 
10
+ static VALUE contrast_assess_prepend_array_join(const int argc, const VALUE *argv,
11
+ const VALUE ary);
12
+
10
13
  void Init_cs__assess_array(void);
@@ -1,7 +1,6 @@
1
1
  # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/assess/events/event_factory'
5
4
  require 'contrast/agent/assess/policy/trigger_validation/trigger_validation'
6
5
  require 'contrast/agent/excluder'
7
6
  require 'contrast/components/logger'
@@ -15,6 +14,7 @@ require 'contrast/agent/reporting/reporting_events/preflight_message'
15
14
  require 'contrast/agent/reporting/reporting_events/route_discovery'
16
15
  require 'contrast/agent/reporting/reporting_utilities/reporting_storage'
17
16
  require 'contrast/agent/reporting/reporting_utilities/build_preflight'
17
+ require 'contrast/utils/assess/event_limit_utils'
18
18
 
19
19
  module Contrast
20
20
  module Agent
@@ -23,7 +23,7 @@ module Contrast
23
23
  # A trigger method is one which can perform a dangerous action, as described by the
24
24
  # Contrast::Agent::Assess::Policy::TriggerNode class. Each such method will call to this module just after
25
25
  # invocation in order to determine if the call was done safely. In those cases where it was not, a Finding
26
- # report is issued to the Service.
26
+ # report is issued to TeamServer.
27
27
  module TriggerMethod
28
28
  extend Contrast::Components::Logger::InstanceMethods
29
29
  extend Contrast::Utils::Assess::TriggerMethodUtils
@@ -105,7 +105,7 @@ module Contrast
105
105
  nil
106
106
  end
107
107
 
108
- # Given a finding, append it to an activity message and send it to the Service for processing. If an
108
+ # Given a finding, append it to an activity message and send it to the TeamServer for processing. If an
109
109
  # activity message does not exist, b/c we're invoked outside of a request context, build an activity and
110
110
  # immediately report it with the finding.
111
111
  #
@@ -7,7 +7,7 @@ module Contrast
7
7
  module Policy
8
8
  module TriggerValidation
9
9
  # Validator used to assert a REDOS finding is actually vulnerable
10
- # before serializing that finding as a DTM to report to the service.
10
+ # before serializing that finding as a DTM to report to the TeamServer.
11
11
  module REDOSValidator
12
12
  RULE_NAME = 'redos'
13
13
 
@@ -7,7 +7,7 @@ module Contrast
7
7
  module Policy
8
8
  module TriggerValidation
9
9
  # Validator used to assert a SSRF finding is actually vulnerable
10
- # before serializing that finding as a DTM to report to the service.
10
+ # before serializing that finding as a DTM to report to the TeamServer.
11
11
  module SSRFValidator
12
12
  RULE_NAME = 'ssrf'
13
13
  URL_PATTERN = %r{(?<protocol>http|https|ftp|sftp|telnet|gopher|rtsp|rtsps|ssh|svn)://(?<host>[^/?]+)(?<path>/?[^?]*)(?<query_string>\?.*)?}i.cs__freeze # rubocop:disable Layout/LineLength
@@ -8,7 +8,7 @@ module Contrast
8
8
  module TriggerValidation
9
9
  # Validator used to assert a Reflected XSS finding is actually
10
10
  # vulnerable before serializing that finding as a DTM to report to
11
- # the service.
11
+ # the TeamServer.
12
12
  module XSSValidator
13
13
  RULE_NAME = 'reflected-xss'
14
14
  SAFE_CONTENT_TYPES = %w[/csv /javascript /json /pdf /x-javascript /x-json].cs__freeze
@@ -1,8 +1,7 @@
1
1
  # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/assess/events/event_factory'
5
- require 'contrast/agent/assess/events/source_event'
4
+ require 'contrast/agent/reporting/reporting_events/finding_event'
6
5
 
7
6
  module Contrast
8
7
  module Agent
@@ -25,7 +24,7 @@ module Contrast
25
24
  # the key used to accessed if from a map or nil if a type like
26
25
  # BODY
27
26
  def build_event event_data, source_type = nil, source_name = nil
28
- @event = Contrast::Agent::Assess::Events::EventFactory.build(event_data, source_type, source_name)
27
+ @event = Contrast::Agent::Reporting::FindingEvent.new(event_data, source_type, source_name)
29
28
  report_sources(event_data.tagged, @event)
30
29
  end
31
30
 
@@ -35,21 +34,22 @@ module Contrast
35
34
  # context's observed route
36
35
  #
37
36
  # @param tagged [Object] The Target of the Event
38
- # @param event [Contrast::Agent::Assess::Events::ContrastEvent]
37
+ # @param event [Contrast::Agent::Reporting::FindingEvent]
39
38
  def report_sources tagged, event
40
39
  return unless tagged && !tagged.to_s.empty?
41
- return unless event.cs__is_a?(Contrast::Agent::Assess::Events::SourceEvent)
42
40
  return unless event.source_type
43
41
  return unless (current_request = Contrast::Agent::REQUEST_TRACKER.current)
44
42
 
45
- if current_request.observed_route.sources.any? do |source|
46
- source.type == event.source_type && source.name == event.source_name # rubocop:disable Security/Module/Name
47
- end
43
+ event.event_sources&.each do |event_source|
44
+ if current_request.observed_route.sources.any? do |source|
45
+ source.source_type == event_source.source_type && source.source_name == event_source.source_name
46
+ end
48
47
 
49
- return
50
- end
48
+ next
49
+ end
51
50
 
52
- current_request.observed_route.sources << event.event_source if event.event_source
51
+ current_request.observed_route.sources << event_source
52
+ end
53
53
  end
54
54
  end
55
55
  end
@@ -18,7 +18,6 @@ module Contrast
18
18
  # reporting / tracking
19
19
  require 'contrast/agent/assess/properties'
20
20
  require 'contrast/agent/assess/tag'
21
- require 'contrast/agent/assess/events/event_factory'
22
21
  end
23
22
  end
24
23
  end
@@ -1,13 +1,17 @@
1
1
  # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'contrast/agent/reporting/settings/url_exclusion'
5
+
4
6
  module Contrast
5
7
  module Agent
6
8
  # Given an array of exclusion matcher instances provides methods to
7
9
  # determine if the exclusions apply to particular urls.
8
10
  class Excluder # rubocop:disable Metrics/ClassLength
11
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
9
12
  attr_reader :exclusions
10
13
 
14
+ # @param exclusions [Array<Contrast::Agent::ExclusionMatcher>]
11
15
  def initialize exclusions = []
12
16
  @exclusions = exclusions
13
17
  end
@@ -16,12 +20,12 @@ module Contrast
16
20
  # then we can avoid any tracking for the request.
17
21
  #
18
22
  # @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
19
- # return [Boolean]
23
+ # @return [Boolean]
20
24
  def assess_excluded_by_url? request
21
25
  request_path = request.path
22
26
 
23
- assess_url_exclusions_for_all_rules.any? do |exclusion|
24
- path_match?(exclusion, request_path)
27
+ assess_url_exclusions_for_all_rules.any? do |exclusion_matcher|
28
+ path_match?(exclusion_matcher, request_path)
25
29
  end
26
30
  end
27
31
 
@@ -34,9 +38,9 @@ module Contrast
34
38
  def assess_excluded_by_url_and_rule? request, rule_id
35
39
  request_path = request.path
36
40
 
37
- assess_url_exclusions.any? do |exclusion|
38
- path_match?(exclusion, request_path) &&
39
- (exclusion.assessment_rules.empty? || exclusion.assessment_rules.include?(rule_id))
41
+ assess_url_exclusions.any? do |exclusion_matcher|
42
+ path_match?(exclusion_matcher, request_path) &&
43
+ (exclusion_matcher.assess_rules.empty? || exclusion_matcher.assess_rules.include?(rule_id))
40
44
  end
41
45
  end
42
46
 
@@ -44,13 +48,14 @@ module Contrast
44
48
  # rules, then we can avoid tracking this entry.
45
49
  #
46
50
  # @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
47
- # @param rule_id [String]
51
+ # @param source_type [String]
52
+ # @param source_name [String]
48
53
  # return [Boolean]
49
54
  def assess_excluded_by_input? request, source_type, source_name
50
55
  request_path = request.path
51
56
 
52
- assess_input_exclusions_for_all_rules.any? do |exclusion|
53
- input_match?(exclusion, source_type, source_name) && path_match?(exclusion, request_path)
57
+ assess_input_exclusions_for_all_rules.any? do |exclusion_matcher|
58
+ input_match?(exclusion_matcher, source_type, source_name) && path_match?(exclusion_matcher, request_path)
54
59
  end
55
60
  end
56
61
 
@@ -66,18 +71,18 @@ module Contrast
66
71
 
67
72
  # We need to check for url exclusions here for the input rules as the url exclusions
68
73
  # that have already been checked didn't include the INPUT exclusions. So we look for
69
- # any INPUT exclusions that apply to the current url and the suppleid rule.
74
+ # any INPUT exclusions that apply to the current url and the supplied rule.
70
75
  path = request.path
71
- rule_input_exclusions = assess_input_exclusions.select do |exclusion|
72
- (exclusion.protection_rules.empty? || exclusion.protection_rules.include?(rule)) && path_match?(exclusion,
73
- path)
76
+ rule_input_exclusions = assess_input_exclusions.select do |exclusion_matcher|
77
+ (exclusion_matcher.protection_rules.empty? || exclusion_matcher.protection_rules.include?(rule)) &&
78
+ path_match?(exclusion_matcher, path)
74
79
  end
75
80
  return false if rule_input_exclusions.empty?
76
81
 
77
82
  event_sources = finding.events.flat_map(&:event_sources)
78
83
  event_sources.each do |event_source|
79
84
  return false unless rule_input_exclusions.any? do |exclusion|
80
- input_match?(exclusion, event_source.type, event_source.name) # rubocop:disable Security/Module/Name
85
+ input_match?(exclusion, event_source.source_type, event_source.source_name)
81
86
  end
82
87
  end
83
88
 
@@ -94,72 +99,85 @@ module Contrast
94
99
  def protect_excluded_by_url? request
95
100
  request_path = request.path
96
101
 
97
- protect_url_exclusions_for_all_rules.any? do |exclusion|
98
- path_match?(exclusion, request_path)
102
+ protect_url_exclusions_for_all_rules.any? do |exclusion_matcher|
103
+ path_match?(exclusion_matcher, request_path)
99
104
  end
100
105
  end
101
106
 
102
107
  private
103
108
 
109
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
104
110
  def assess_url_exclusions_for_all_rules
105
- @_assess_url_exclusions_for_all_rules ||= assess_url_exclusions.select do |exclusion|
106
- exclusion.assessment_rules.empty?
111
+ @_assess_url_exclusions_for_all_rules ||= assess_url_exclusions.select do |exclusion_matcher|
112
+ exclusion_matcher.assess_rules.empty?
107
113
  end
108
114
  end
109
115
 
116
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
110
117
  def assess_url_exclusions
111
- @_assess_url_exclusions ||= assess_exclusions.select do |exclusion|
112
- exclusion.type == Contrast::Api::Settings::Exclusion::ExclusionType::URL
118
+ @_assess_url_exclusions ||= assess_exclusions.select do |exclusion_matcher|
119
+ exclusion_matcher.type == :URL
113
120
  end
114
121
  end
115
122
 
123
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
116
124
  def assess_input_exclusions_for_all_rules
117
- @_assess_input_exclusions_for_all_rules ||= assess_input_exclusions.select do |exclusion|
118
- exclusion.assessment_rules.empty?
125
+ @_assess_input_exclusions_for_all_rules ||= assess_input_exclusions.select do |exclusion_matcher|
126
+ exclusion_matcher.assess_rules.empty?
119
127
  end
120
128
  end
121
129
 
130
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
122
131
  def assess_input_exclusions
123
- @_assess_input_exclusions ||= assess_exclusions.select do |exclusion|
124
- exclusion.type == Contrast::Api::Settings::Exclusion::ExclusionType::INPUT
132
+ @_assess_input_exclusions ||= assess_exclusions.select do |exclusion_matcher|
133
+ exclusion_matcher.type == :INPUT
125
134
  end
126
135
  end
127
136
 
137
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
128
138
  def assess_exclusions
129
139
  @_assess_exclusions ||= @exclusions.select(&:assess)
130
140
  end
131
141
 
142
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
132
143
  def protect_url_exclusions_for_all_rules
133
- @_protect_url_exclusions_for_all_rules ||= protect_url_exclusions.select do |exclusion|
134
- exclusion.protection_rules.empty?
144
+ @_protect_url_exclusions_for_all_rules ||= protect_url_exclusions.select do |exclusion_matcher|
145
+ exclusion_matcher.protect_rules.empty?
135
146
  end
136
147
  end
137
148
 
149
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
138
150
  def protect_url_exclusions
139
- @_protect_url_exclusions ||= protect_exclusions.select do |exclusion|
140
- exclusion.type == Contrast::Api::Settings::Exclusion::ExclusionType::URL
151
+ @_protect_url_exclusions ||= protect_exclusions.select do |exclusion_matcher|
152
+ exclusion_matcher.type == :URL
141
153
  end
142
154
  end
143
155
 
156
+ # @return [Array<Contrast::Agent::ExclusionMatcher>]
144
157
  def protect_exclusions
145
158
  @_protect_exclusions ||= @exclusions.select(&:protect)
146
159
  end
147
160
 
148
- def path_match? exclusion, path
149
- exclusion.wildcard_url || exclusion.urls.any? { |url| url.match?(path) }
161
+ # @return [Boolean]
162
+ def path_match? exclusion_matcher, path
163
+ exclusion_matcher.wildcard_url || exclusion_matcher.urls.any? { |url| url.match?(path) }
150
164
  end
151
165
 
166
+ # @param exclusion [Contrast::Agent::ExclusionMatcher]
167
+ # @param source_type [String]
168
+ # @param source_name [String]
169
+ # @return [Boolean]
152
170
  def input_match? exclusion, source_type, source_name
153
171
  case exclusion.input_type
154
- when Contrast::Api::Settings::Exclusion::InputType::PARAMETER
172
+ when 'PARAMETER'
155
173
  input_match_parameter?(exclusion, source_type, source_name)
156
- when Contrast::Api::Settings::Exclusion::InputType::COOKIE
174
+ when 'COOKIE'
157
175
  input_match_cookie?(exclusion, source_type, source_name)
158
- when Contrast::Api::Settings::Exclusion::InputType::HEADER
176
+ when 'HEADER'
159
177
  input_match_header?(exclusion, source_type, source_name)
160
- when Contrast::Api::Settings::Exclusion::InputType::BODY
178
+ when 'BODY'
161
179
  Contrast::Agent::Assess::Policy::SourceMethod::BODY_TYPE == source_type
162
- when Contrast::Api::Settings::Exclusion::InputType::QUERYSTRING
180
+ when 'QUERYSTRING'
163
181
  Contrast::Agent::Assess::Policy::SourceMethod::QUERYSTRING_TYPE == source_type
164
182
  else
165
183
  false
@@ -2,6 +2,10 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/components/logger'
5
+ require 'contrast/agent/reporting/settings/exclusion_base'
6
+ require 'contrast/agent/reporting/settings/code_exclusion'
7
+ require 'contrast/agent/reporting/settings/input_exclusion'
8
+ require 'contrast/agent/reporting/settings/url_exclusion'
5
9
 
6
10
  module Contrast
7
11
  module Agent
@@ -13,22 +17,30 @@ module Contrast
13
17
 
14
18
  extend Forwardable
15
19
 
16
- attr_reader :protect, :assess, :urls, :wildcard_url, :wildcard_input
20
+ attr_reader :protect, :assess, :type, :urls, :wildcard_url, :wildcard_input
17
21
 
18
- def_delegators :@exclusion, :type, :assessment_rules, :protection_rules, :input_type, :input_name
22
+ def_delegators :@exclusion, :protect_rules, :assess_rules, :input_type, :input_name
19
23
 
20
24
  # Create a matcher around an exclusion sent from TeamServer.
21
25
  #
22
- # @param excl [Contrast::Api::Settings::Exclusion]
26
+ # @param excl [Contrast::Agent::Reporting::Settings::ExclusionBase]
23
27
  # @return [Contrast::Agent::ExclusionMatcher]
24
28
  def initialize excl
25
29
  @exclusion = excl
26
30
  @protect = @exclusion.protect
27
31
  @assess = @exclusion.assess
28
32
 
29
- handle_wildcard_input
30
- handle_wildcard_url
31
- handle_wildcard_code
33
+ case excl
34
+ when Contrast::Agent::Reporting::Settings::CodeExclusion
35
+ handle_wildcard_code
36
+ @type = :CODE
37
+ when Contrast::Agent::Reporting::Settings::InputExclusion
38
+ handle_wildcard_input
39
+ @type = :INPUT
40
+ when Contrast::Agent::Reporting::Settings::UrlExclusion
41
+ handle_wildcard_url
42
+ @type = :URL
43
+ end
32
44
  end
33
45
 
34
46
  # According to the docs for exclusions, user input applies to all inputs if
@@ -97,7 +109,7 @@ module Contrast
97
109
  end
98
110
 
99
111
  def code?
100
- @exclusion.type == Contrast::Api::Settings::Exclusion::ExclusionType::CODE
112
+ @type == :CODE
101
113
  end
102
114
 
103
115
  def match_all?
@@ -105,12 +117,12 @@ module Contrast
105
117
  end
106
118
 
107
119
  # Determine if the given rule is excluded by this exclusion.
108
- # In this case, the `protection_rules` being empty means apply to all rules,
120
+ # In this case, the `protect_rules` being empty means apply to all rules,
109
121
  # not no rules
110
122
  #
111
123
  # @param rule - the id of the rule which we're checking for exclusion
112
124
  def protection_rule? rule
113
- protect? && (@exclusion.protection_rules.empty? || @exclusion.protection_rules.include?(rule))
125
+ protect? && (@exclusion.protect_rules.empty? || @exclusion.protect_rules.include?(rule))
114
126
  end
115
127
 
116
128
  # Determine if the given rule is excluded by this exclusion.
@@ -15,7 +15,7 @@ require 'contrast/agent/request_handler'
15
15
  require 'contrast/agent/static_analysis'
16
16
  require 'contrast/agent/telemetry/events/startup_metrics_event'
17
17
  require 'contrast/utils/middleware_utils'
18
-
18
+ require 'contrast/utils/reporting/application_activity_batch_utils'
19
19
  require 'contrast/utils/timer'
20
20
 
21
21
  module Contrast
@@ -27,6 +27,7 @@ module Contrast
27
27
  include Contrast::Components::Logger::InstanceMethods
28
28
  include Contrast::Components::Scope::InstanceMethods
29
29
  include Contrast::Utils::MiddlewareUtils
30
+ include Contrast::Utils::Reporting::ApplicationActivityBatchUtils
30
31
 
31
32
  attr_reader :app
32
33
 
@@ -62,6 +63,7 @@ module Contrast
62
63
  # the Rack framework.
63
64
  def call env
64
65
  logger.trace_with_time('Elapsed time for Contrast::Agent::Middleware#call') do
66
+ ::Contrast::Agent::ThreadWatcher.check_before_start
65
67
  return app.call(env) unless ::Contrast::AGENT.enabled?
66
68
 
67
69
  Contrast::Agent.heapdump_util.start_thread!
@@ -73,12 +75,12 @@ module Contrast
73
75
  private
74
76
 
75
77
  # Startup the Agent as part of the initialization process:
76
- # - start the service sending thread, responsible for sending and processing messages
77
- # - start the heartbeat thread, which triggers service startup
78
+ # - start the TeamServer sending thread, responsible for sending and processing messages
79
+ # - start the heartbeat thread, which handles periodic messages to TeamServer
78
80
  # - start instrumenting libraries and do a 'catchup' patch for everything we didn't see get loaded
79
81
  # - enable TracePoint, which handles all class loads and required instrumentation going forward
80
82
  def agent_startup_routine
81
- logger.debug_with_time('middleware: starting service') do
83
+ logger.debug_with_time('middleware: starting reporting threads') do
82
84
  Contrast::Agent.thread_watcher.ensure_running?
83
85
  end
84
86
 
@@ -147,7 +149,7 @@ module Contrast
147
149
  # which is being triggered when there is a failure within the pre-call with the agent
148
150
  def pre_call_with_agent context, request_handler
149
151
  with_contrast_scope do
150
- context.service_extract_request
152
+ context.protect_input_analysis
151
153
  request_handler.ruleset.prefilter
152
154
  end
153
155
  rescue StandardError => e
@@ -173,13 +175,17 @@ module Contrast
173
175
  Contrast::Agent::FINDINGS.report_collected_findings unless Contrast::Agent::FINDINGS.collection.empty?
174
176
  # All protect rules, which are trigger but require response to be reported
175
177
  Contrast::Agent::EXPLOITS.report_recorded_exploits(context) unless Contrast::Agent::EXPLOITS.collection.empty?
178
+ # Process Worth Watching Inputs for v2 rules
179
+ Contrast::Agent.worth_watching_analyzer&.add_to_queue(context.agent_input_analysis)
176
180
 
177
181
  if Contrast::Agent.framework_manager.streaming?(env)
178
182
  context.reset_activity
179
183
  request_handler.stream_safe_postfilter
180
184
  else
181
185
  request_handler.ruleset.postfilter
182
- request_handler.report_activity
186
+ request_handler.report_observed_route
187
+ add_activity_to_batch(context.activity)
188
+ report_batch
183
189
  end
184
190
  end
185
191
  # unsuccessful attack
@@ -56,6 +56,7 @@ module Contrast
56
56
  unless Contrast::Agent::Assess.cs__object_method_prepended?(Marshal, :load, false)
57
57
  apply_marshal_load_alias_patch
58
58
  end
59
+ apply_array_join_prepend_patch if Contrast::Agent::Assess.cs__object_method_prepended?(Array, :join, true)
59
60
  true
60
61
  end
61
62
  end
@@ -121,6 +122,11 @@ module Contrast
121
122
  Marshal.alias_method(:cs__marshal_load, :load)
122
123
  Marshal.alias_method(:load, :cs__marshal_load)
123
124
  end
125
+
126
+ # Prepend Contrast::Extension::Assess::ContrastArray to pick up the ContrastArray#join method
127
+ def apply_array_join_prepend_patch
128
+ Array.prepend(Contrast::Extension::Assess::ContrastArray)
129
+ end
124
130
  end
125
131
  end
126
132
  end