contrast-agent 6.7.0 → 6.9.0

Sign up to get free protection for your applications and to get access to all the features.
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