Package not found. Please check the package name and try again.

contrast-agent 6.1.2 → 6.4.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 (220) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -3
  3. data/.simplecov +1 -0
  4. data/Rakefile +0 -27
  5. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +7 -5
  6. data/ext/cs__assess_kernel/cs__assess_kernel.c +14 -3
  7. data/ext/cs__assess_kernel/cs__assess_kernel.h +2 -0
  8. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +10 -3
  9. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +2 -1
  10. data/ext/cs__assess_regexp/cs__assess_regexp.c +9 -7
  11. data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.c → cs__assess_string_interpolation/cs__assess_string_interpolation.c} +14 -3
  12. data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.h → cs__assess_string_interpolation/cs__assess_string_interpolation.h} +1 -1
  13. data/ext/{cs__assess_string_interpolation26 → cs__assess_string_interpolation}/extconf.rb +0 -0
  14. data/ext/cs__common/cs__common.c +5 -4
  15. data/ext/cs__contrast_patch/cs__contrast_patch.c +3 -10
  16. data/lib/contrast/agent/assess/events/source_event.rb +16 -12
  17. data/lib/contrast/agent/assess/policy/policy_node.rb +6 -0
  18. data/lib/contrast/agent/assess/policy/propagation_method.rb +3 -41
  19. data/lib/contrast/agent/assess/policy/propagation_node.rb +8 -0
  20. data/lib/contrast/agent/assess/policy/propagator/base.rb +2 -0
  21. data/lib/contrast/agent/assess/policy/source_method.rb +2 -47
  22. data/lib/contrast/agent/assess/policy/source_node.rb +1 -0
  23. data/lib/contrast/agent/assess/policy/trigger_method.rb +1 -1
  24. data/lib/contrast/agent/assess/policy/trigger_node.rb +8 -0
  25. data/lib/contrast/agent/assess/property/evented.rb +4 -18
  26. data/lib/contrast/agent/assess/tag.rb +19 -0
  27. data/lib/contrast/agent/at_exit_hook.rb +9 -8
  28. data/lib/contrast/agent/inventory/database_config.rb +6 -3
  29. data/lib/contrast/agent/inventory/dependency_analysis.rb +3 -2
  30. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +13 -9
  31. data/lib/contrast/agent/middleware.rb +4 -0
  32. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +27 -2
  33. data/lib/contrast/agent/patching/policy/policy.rb +5 -0
  34. data/lib/contrast/agent/patching/policy/policy_node.rb +6 -0
  35. data/lib/contrast/agent/patching/policy/trigger_node.rb +3 -0
  36. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +3 -4
  37. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -0
  38. data/lib/contrast/agent/protect/policy/rule_applicator.rb +2 -2
  39. data/lib/contrast/agent/protect/rule/base.rb +1 -0
  40. data/lib/contrast/agent/protect/rule/no_sqli.rb +2 -0
  41. data/lib/contrast/agent/protect/rule/xss.rb +4 -0
  42. data/lib/contrast/agent/reporting/reporter.rb +33 -17
  43. data/lib/contrast/agent/reporting/reporter_heartbeat.rb +21 -15
  44. data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +3 -18
  45. data/lib/contrast/agent/reporting/reporting_events/application_update.rb +5 -24
  46. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +8 -1
  47. data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +83 -16
  48. data/lib/contrast/agent/reporting/reporting_events/finding.rb +9 -3
  49. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +10 -1
  50. data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +11 -1
  51. data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +11 -1
  52. data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +12 -1
  53. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -1
  54. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +11 -1
  55. data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +11 -1
  56. data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +11 -1
  57. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +11 -1
  58. data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +29 -32
  59. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +18 -20
  60. data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +11 -24
  61. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +13 -6
  62. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -4
  63. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +10 -4
  64. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +9 -0
  65. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +10 -1
  66. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +11 -4
  67. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -8
  68. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +2 -6
  69. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -32
  70. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -4
  71. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +1 -11
  72. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +60 -2
  73. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +32 -10
  74. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
  75. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +58 -26
  76. data/lib/contrast/agent/reporting/settings/application_settings.rb +8 -23
  77. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +27 -33
  78. data/lib/contrast/agent/reporting/settings/bot_blocker.rb +68 -0
  79. data/lib/contrast/agent/reporting/settings/code_exclusion.rb +27 -0
  80. data/lib/contrast/agent/reporting/settings/exclusion_base.rb +33 -0
  81. data/lib/contrast/agent/reporting/settings/exclusions.rb +39 -57
  82. data/lib/contrast/agent/reporting/settings/helpers.rb +56 -0
  83. data/lib/contrast/agent/reporting/settings/input_exclusion.rb +37 -0
  84. data/lib/contrast/agent/reporting/settings/ip_filter.rb +35 -0
  85. data/lib/contrast/agent/reporting/settings/keyword.rb +74 -0
  86. data/lib/contrast/agent/reporting/settings/log_enhancer.rb +65 -0
  87. data/lib/contrast/agent/reporting/settings/protect.rb +4 -2
  88. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +62 -115
  89. data/lib/contrast/agent/reporting/settings/reaction.rb +11 -2
  90. data/lib/contrast/agent/reporting/settings/rule_definition.rb +63 -0
  91. data/lib/contrast/agent/reporting/settings/sampling.rb +10 -0
  92. data/lib/contrast/agent/reporting/settings/sanitizer.rb +38 -0
  93. data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +9 -1
  94. data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +7 -0
  95. data/lib/contrast/agent/reporting/settings/server_features.rb +8 -0
  96. data/lib/contrast/agent/reporting/settings/syslog.rb +176 -0
  97. data/lib/contrast/agent/reporting/settings/url_exclusion.rb +42 -0
  98. data/lib/contrast/agent/reporting/settings/validator.rb +17 -0
  99. data/lib/contrast/agent/request.rb +5 -7
  100. data/lib/contrast/agent/request_context.rb +8 -13
  101. data/lib/contrast/agent/request_context_extend.rb +8 -9
  102. data/lib/contrast/agent/request_handler.rb +10 -35
  103. data/lib/contrast/agent/rule_set.rb +4 -0
  104. data/lib/contrast/agent/service_heartbeat.rb +1 -1
  105. data/lib/contrast/agent/static_analysis.rb +6 -15
  106. data/lib/contrast/agent/telemetry/base.rb +35 -35
  107. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +2 -0
  108. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +2 -0
  109. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +5 -2
  110. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +3 -0
  111. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +3 -0
  112. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +0 -1
  113. data/lib/contrast/agent/thread_watcher.rb +2 -6
  114. data/lib/contrast/agent/version.rb +1 -1
  115. data/lib/contrast/agent.rb +1 -3
  116. data/lib/contrast/api/communication/socket.rb +1 -0
  117. data/lib/contrast/api/decorators/message.rb +0 -6
  118. data/lib/contrast/api/decorators.rb +0 -3
  119. data/lib/contrast/api/dtm.pb.rb +1 -1
  120. data/lib/contrast/api/settings.pb.rb +1 -1
  121. data/lib/contrast/components/assess.rb +0 -6
  122. data/lib/contrast/components/config.rb +18 -2
  123. data/lib/contrast/config/base_configuration.rb +0 -13
  124. data/lib/contrast/config/root_configuration.rb +1 -0
  125. data/lib/contrast/config/ruby_configuration.rb +2 -9
  126. data/lib/contrast/configuration.rb +0 -2
  127. data/lib/contrast/extension/assess/eval_trigger.rb +0 -4
  128. data/lib/contrast/extension/assess/hash.rb +3 -2
  129. data/lib/contrast/extension/assess/kernel.rb +22 -0
  130. data/lib/contrast/extension/assess/marshal.rb +16 -0
  131. data/lib/contrast/extension/assess/string.rb +21 -20
  132. data/lib/contrast/framework/base_support.rb +13 -4
  133. data/lib/contrast/framework/grape/support.rb +6 -6
  134. data/lib/contrast/framework/manager.rb +7 -23
  135. data/lib/contrast/framework/manager_extend.rb +1 -1
  136. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +11 -15
  137. data/lib/contrast/framework/rails/support.rb +9 -2
  138. data/lib/contrast/framework/sinatra/support.rb +3 -2
  139. data/lib/contrast/logger/aliased_logging.rb +33 -26
  140. data/lib/contrast/utils/assess/source_method_utils.rb +0 -9
  141. data/lib/contrast/utils/lru_cache.rb +3 -0
  142. data/lib/contrast/utils/middleware_utils.rb +2 -0
  143. data/lib/contrast/utils/patching/policy/patch_utils.rb +5 -22
  144. data/lib/contrast/utils/response_utils.rb +14 -1
  145. data/lib/contrast/utils/telemetry.rb +9 -0
  146. data/lib/contrast/utils/telemetry_client.rb +7 -7
  147. data/lib/contrast/utils/telemetry_hash.rb +36 -12
  148. data/lib/contrast/utils/telemetry_identifier.rb +8 -0
  149. data/lib/contrast/utils/thread_tracker.rb +26 -9
  150. data/lib/contrast/utils/timer.rb +6 -1
  151. data/lib/contrast.rb +35 -3
  152. data/lib/protobuf/code_generator.rb +129 -0
  153. data/lib/protobuf/decoder.rb +28 -0
  154. data/lib/protobuf/deprecation.rb +117 -0
  155. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +79 -0
  156. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +360 -0
  157. data/lib/protobuf/descriptors.rb +3 -0
  158. data/lib/protobuf/encoder.rb +11 -0
  159. data/lib/protobuf/enum.rb +365 -0
  160. data/lib/protobuf/exceptions.rb +9 -0
  161. data/lib/protobuf/field/base_field.rb +380 -0
  162. data/lib/protobuf/field/base_field_object_definitions.rb +504 -0
  163. data/lib/protobuf/field/bool_field.rb +64 -0
  164. data/lib/protobuf/field/bytes_field.rb +67 -0
  165. data/lib/protobuf/field/double_field.rb +25 -0
  166. data/lib/protobuf/field/enum_field.rb +56 -0
  167. data/lib/protobuf/field/field_array.rb +102 -0
  168. data/lib/protobuf/field/field_hash.rb +122 -0
  169. data/lib/protobuf/field/fixed32_field.rb +25 -0
  170. data/lib/protobuf/field/fixed64_field.rb +28 -0
  171. data/lib/protobuf/field/float_field.rb +43 -0
  172. data/lib/protobuf/field/int32_field.rb +21 -0
  173. data/lib/protobuf/field/int64_field.rb +34 -0
  174. data/lib/protobuf/field/integer_field.rb +23 -0
  175. data/lib/protobuf/field/message_field.rb +51 -0
  176. data/lib/protobuf/field/sfixed32_field.rb +27 -0
  177. data/lib/protobuf/field/sfixed64_field.rb +28 -0
  178. data/lib/protobuf/field/signed_integer_field.rb +29 -0
  179. data/lib/protobuf/field/sint32_field.rb +21 -0
  180. data/lib/protobuf/field/sint64_field.rb +21 -0
  181. data/lib/protobuf/field/string_field.rb +51 -0
  182. data/lib/protobuf/field/uint32_field.rb +21 -0
  183. data/lib/protobuf/field/uint64_field.rb +21 -0
  184. data/lib/protobuf/field/varint_field.rb +77 -0
  185. data/lib/protobuf/field.rb +74 -0
  186. data/lib/protobuf/generators/base.rb +85 -0
  187. data/lib/protobuf/generators/enum_generator.rb +39 -0
  188. data/lib/protobuf/generators/extension_generator.rb +27 -0
  189. data/lib/protobuf/generators/field_generator.rb +193 -0
  190. data/lib/protobuf/generators/file_generator.rb +262 -0
  191. data/lib/protobuf/generators/group_generator.rb +122 -0
  192. data/lib/protobuf/generators/message_generator.rb +104 -0
  193. data/lib/protobuf/generators/option_generator.rb +17 -0
  194. data/lib/protobuf/generators/printable.rb +160 -0
  195. data/lib/protobuf/generators/service_generator.rb +50 -0
  196. data/lib/protobuf/lifecycle.rb +33 -0
  197. data/lib/protobuf/logging.rb +39 -0
  198. data/lib/protobuf/message/fields.rb +233 -0
  199. data/lib/protobuf/message/serialization.rb +85 -0
  200. data/lib/protobuf/message.rb +241 -0
  201. data/lib/protobuf/optionable.rb +72 -0
  202. data/lib/protobuf/tasks/compile.rake +80 -0
  203. data/lib/protobuf/tasks.rb +1 -0
  204. data/lib/protobuf/varint.rb +20 -0
  205. data/lib/protobuf/varint_pure.rb +31 -0
  206. data/lib/protobuf/version.rb +3 -0
  207. data/lib/protobuf/wire_type.rb +10 -0
  208. data/lib/protobuf.rb +91 -0
  209. data/proto/dynamic_discovery.proto +46 -0
  210. data/proto/google/protobuf/compiler/plugin.proto +183 -0
  211. data/proto/google/protobuf/descriptor.proto +911 -0
  212. data/proto/rpc.proto +71 -0
  213. data/resources/assess/policy.json +2 -11
  214. data/ruby-agent.gemspec +2 -2
  215. metadata +105 -30
  216. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +0 -30
  217. data/lib/contrast/api/decorators/application_update.rb +0 -52
  218. data/lib/contrast/api/decorators/library.rb +0 -56
  219. data/lib/contrast/api/decorators/library_usage_update.rb +0 -31
  220. data/lib/contrast/framework/platform_version.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c901ed882ebff8176fe2f3794907e29b03cc2903b61260f138d93b2ef02a465c
4
- data.tar.gz: 72e4f01ccf5a57bbd5afa0cac58c51cddbe26183691d9495f563dfd9fb37e7e1
3
+ metadata.gz: d74206aa94d644cbe7c47523a69efdb9c0f27d59604125287fd98b123f0d20d6
4
+ data.tar.gz: d4c28074b8d3f11e968d9c3875bfd16d3de41bdd63452bec470cea65a6c83089
5
5
  SHA512:
6
- metadata.gz: 1d60653e61e95443c45bb43caac325b3c72449ddea435096e2d8e49c0a0851ff9ae6486fc16a17f65f663c2f069c58f6157f4f7ef8745d0b082d4fe7c5c0b8b6
7
- data.tar.gz: e1e5dd1a542009d153fa6e77f86d889d8bb852d85d66c84400a583b63536be06a70423c4f05e547280f06368851a43720ac941efedf3aeb17a314ff3c9f61a14
6
+ metadata.gz: 3dd36988b29722b7961e919d2685a8cafbf001917f54f5e43107cf51fddb7c105cfea368e04f819f01dc388dd75f5bf739f9bb0c58301784c90bf48188c43bd8
7
+ data.tar.gz: 18a2cbb1e4a4e56d64d3a3821c47ec3aca5709f64673ffb0024b26173de7d1ed4aa8213c851c202c1d30c118d73a4f373b14563d3aa3d9f017ea8caa24ead71d
data/.gitignore CHANGED
@@ -56,8 +56,5 @@ contrast-agent-*.gem
56
56
  .ruby-gemset
57
57
  service_executables/*-*
58
58
 
59
- # Generated Protobuf files
60
- /lib/contrast/api/*.pb.rb
61
-
62
59
  # IDE stuff
63
60
  tags
data/.simplecov CHANGED
@@ -4,5 +4,6 @@
4
4
  SimpleCov.minimum_coverage(line: 94)
5
5
  SimpleCov.start do
6
6
  add_filter '/spec/'
7
+ add_filter '/lib/protobuf/'
7
8
  enable_coverage :branch
8
9
  end
data/Rakefile CHANGED
@@ -17,30 +17,3 @@ Dir['ext/cs__*'].each do |extension|
17
17
  ext.lib_dir = "lib/#{ name }"
18
18
  end
19
19
  end
20
-
21
- desc 'compile the protobuf files for the agent, translating them to .rb classes'
22
- task :contrast_pb_compile do
23
- # do some stuff before compile
24
-
25
- # Invoke the protobuf compile task with your sensible defaults
26
- ::Rake::Task['protobuf:compile'].invoke('lib', './agent-service-api/protobuf ./agent-service-api/protobuf/dtm.proto',
27
- 'lib/contrast/api',
28
- nil)
29
-
30
- ::Rake::Task['protobuf:compile'].reenable
31
-
32
- ::Rake::Task['protobuf:compile'].invoke('lib',
33
- './agent-service-api/protobuf ./agent-service-api/protobuf/settings.proto',
34
- 'lib/contrast/api',
35
- nil)
36
-
37
- ['dtm.pb.rb', 'settings.pb.rb'].each do |target_file|
38
- target_path = File.absolute_path(File.join(__dir__, "./lib/contrast/api/#{ target_file }"))
39
- unless File.exist?(target_path)
40
- puts "File not found #{ target_path }"
41
- exit 1
42
- end
43
- end
44
-
45
- puts 'Protobuf copied successfully'
46
- end
@@ -17,9 +17,10 @@
17
17
  * }
18
18
  */
19
19
 
20
- VALUE contrast_check_and_register_instance_patch(
21
- const char *module_name, const char *method_name,
22
- VALUE(c_fn)(const int, VALUE *, const VALUE));
20
+ VALUE contrast_check_and_register_instance_patch(const char *module_name,
21
+ const char *method_name,
22
+ VALUE(c_fn)(const int, VALUE *,
23
+ const VALUE));
23
24
 
24
25
  void contrast_assess_instance_eval_trigger_check(VALUE self, VALUE source,
25
26
  VALUE ret) {
@@ -65,6 +66,7 @@ void Init_cs__assess_basic_object(void) {
65
66
  * but if someone else patched BasicObject#instance_eval,
66
67
  * IDK if this is intentional... noting it. -ajm
67
68
  */
68
- contrast_check_and_register_instance_patch("BasicObject", "instance_eval",
69
- contrast_assess_basic_object_instance_eval);
69
+ contrast_check_and_register_instance_patch(
70
+ "BasicObject", "instance_eval",
71
+ contrast_assess_basic_object_instance_eval);
70
72
  }
@@ -26,14 +26,25 @@ contrast_patched_kernel_exec(const int argc, const VALUE *argv,
26
26
  return rb_funcall(self, rb_sym_assess_kernel_exec, argc, *argv);
27
27
  }
28
28
 
29
+ /* Check and see if the Kernel#exec is already prepended */
30
+ VALUE contrast_is_kernel_exec_prepended() {
31
+ return contrast_check_prepended(
32
+ rb_const_get(rb_cObject, rb_intern("Kernel")), rb_sym_kernel_exec,
33
+ Qfalse);
34
+ }
35
+
29
36
  void Init_cs__assess_kernel(void) {
37
+ VALUE rb_sym_kernel_exec = ID2SYM(rb_intern("exec"));
30
38
  kernel_propagator = rb_define_module_under(core_assess, "KernelPropagator");
31
39
  exec_apply_trigger = rb_intern("apply_trigger");
32
40
 
33
41
  rb_sym_assess_kernel_exec =
34
42
  contrast_register_patch("Kernel", "exec", contrast_patched_kernel_exec);
35
43
 
36
- /* should return the same value as above */
37
- rb_sym_assess_kernel_exec = contrast_register_singleton_patch(
38
- "Kernel", "exec", contrast_patched_kernel_exec);
44
+ /* check if prepended and register singleton patch if true */
45
+ if (contrast_is_kernel_exec_prepended() == Qtrue) {
46
+ /* should return the same value as above */
47
+ rb_sym_assess_kernel_exec = contrast_register_singleton_patch(
48
+ "Kernel", "exec", contrast_patched_kernel_exec);
49
+ }
39
50
  }
@@ -3,6 +3,8 @@
3
3
  static VALUE exec_apply_trigger;
4
4
  static VALUE kernel_propagator;
5
5
  static VALUE rb_sym_assess_kernel_exec;
6
+ static VALUE rb_sym_kernel_exec;
7
+ VALUE contrast_is_kernel_exec_prepended();
6
8
 
7
9
  VALUE
8
10
  contrast_patched_kernel_exec(const int argc, const VALUE *argv,
@@ -18,7 +18,7 @@
18
18
  * return rb_marshal_load_with_proc(port, proc);
19
19
  * }
20
20
  */
21
- static VALUE contrast_marshal_module_load(const int argc, const VALUE *argv) {
21
+ static VALUE contrast_marshal_module_prepend(const int argc, const VALUE *argv) {
22
22
  VALUE result;
23
23
  VALUE source_string;
24
24
 
@@ -67,6 +67,13 @@ void Init_cs__assess_marshal_module(void) {
67
67
  rb_sym_assess_marshal_load = rb_intern("cs__load_assess");
68
68
  rb_sym_protect_marshal_load = rb_intern("cs__load_protect");
69
69
 
70
- contrast_register_singleton_prepend_patch("Marshal", "load",
71
- &contrast_marshal_module_load);
70
+ /* check if prepended called form the after_load_patcher */
71
+ VALUE marshal = rb_const_get(rb_cObject, rb_intern("Marshal"));
72
+ VALUE marshal_load = ID2SYM(rb_intern("load"));
73
+ VALUE is_prepended = contrast_check_prepended(marshal, marshal_load, Qfalse);
74
+
75
+ if (is_prepended == Qtrue) {
76
+ contrast_register_singleton_prepend_patch("Marshal", "load",
77
+ &contrast_marshal_module_prepend);
78
+ }
72
79
  }
@@ -5,6 +5,7 @@ static VALUE marshal_propagator;
5
5
  static VALUE rb_sym_assess_marshal_load;
6
6
  static VALUE rb_sym_protect_marshal_load;
7
7
  static VALUE properties_hash;
8
+ static VALUE marshal, marshal_load, is_prepended;
8
9
 
9
10
  /*
10
11
  * Rails is a jerk. In Rails 5, they decided to do away with the alias chaining
@@ -14,7 +15,7 @@ static VALUE properties_hash;
14
15
  * special case this for now.
15
16
  * -HM (shamelessly commenting on DP's work)
16
17
  */
17
- static VALUE contrast_marshal_module_load(const int argc,
18
+ static VALUE contrast_marshal_module_prepend(const int argc,
18
19
  const VALUE *argv);
19
20
 
20
21
  void Init_cs__assess_marshal_module(void);
@@ -7,15 +7,15 @@
7
7
  #include <ruby.h>
8
8
 
9
9
  extern VALUE contrast_force_patch(const int argc, VALUE *argv) {
10
- return contrast_check_and_register_instance_patch(
10
+ return contrast_check_and_register_instance_patch(
11
11
  "Regexp", "=~", contrast_assess_regexp_equal_squiggle);
12
12
  }
13
13
 
14
14
  /* check if method is prepended and register instance alias or prepend patch */
15
15
  VALUE contrast_check_and_register_instance_patch(const char *module_name,
16
- const char *method_name,
17
- VALUE(c_fn)(const int, VALUE *,
18
- const VALUE));
16
+ const char *method_name,
17
+ VALUE(c_fn)(const int, VALUE *,
18
+ const VALUE));
19
19
 
20
20
  void contrast_alias_method(const VALUE target, const char *to,
21
21
  const char *from);
@@ -58,8 +58,10 @@ void Init_cs__assess_regexp(void) {
58
58
  rb_global_variable(&rb_sym_string);
59
59
  rb_sym_back_ref = ID2SYM(rb_intern("back_ref"));
60
60
  rb_global_variable(&rb_sym_back_ref);
61
- rb_define_singleton_method(assess, "contrast_force_repatch_regexp", contrast_force_patch, 0);
61
+ rb_define_singleton_method(assess, "contrast_force_repatch_regexp",
62
+ contrast_force_patch, 0);
62
63
 
63
- rb_sym_assess_regexp_equal_squiggle = contrast_check_and_register_instance_patch(
64
- "Regexp", "=~", contrast_assess_regexp_equal_squiggle);
64
+ rb_sym_assess_regexp_equal_squiggle =
65
+ contrast_check_and_register_instance_patch(
66
+ "Regexp", "=~", contrast_assess_regexp_equal_squiggle);
65
67
  }
@@ -1,14 +1,25 @@
1
1
  /* Copyright (c) 2022 Contrast Security, Inc. See
2
2
  * https://www.contrastsecurity.com/enduser-terms-0317a for more details. */
3
3
 
4
- #include "cs__assess_string_interpolation26.h"
4
+ #include "cs__assess_string_interpolation.h"
5
5
  #include "../cs__common/cs__common.h"
6
+ #include "../cs__scope/cs__scope.h"
6
7
  #include <ruby.h>
7
8
 
8
9
  static VALUE rb_str_concat_literals_hook(size_t num, VALUE *strary) {
9
10
  VALUE result = rb_str_concat_literals_original(num, strary);
10
11
  VALUE rb_params = rb_ary_new_from_values((int)num, strary);
11
- rb_funcall(string_propagator, track_interpolation, 2, rb_params, result);
12
+ VALUE in_contrast_scope = inst_methods_in_cntr_scope(contrast_patcher(), 0);
13
+
14
+ if (in_contrast_scope == Qfalse) {
15
+ /* enter scope */
16
+ inst_methods_enter_cntr_scope(contrast_patcher(), 0);
17
+ rb_funcall(string_propagator, track_interpolation, 2, rb_params,
18
+ result);
19
+ /* exit scope */
20
+ inst_methods_exit_cntr_scope(contrast_patcher(), 0);
21
+ }
22
+
12
23
  return result;
13
24
  }
14
25
 
@@ -20,7 +31,7 @@ static int install_hooks() {
20
31
  return 0;
21
32
  }
22
33
 
23
- void Init_cs__assess_string_interpolation26(void) {
34
+ void Init_cs__assess_string_interpolation(void) {
24
35
  string_propagator =
25
36
  rb_define_class_under(core_assess, "StringPropagator", rb_cObject);
26
37
  track_interpolation = rb_intern("track_interpolation");
@@ -10,4 +10,4 @@ static VALUE rb_str_concat_literals_hook(size_t num, VALUE *strary);
10
10
 
11
11
  static int install_hooks();
12
12
 
13
- void Init_cs__assess_string_interpolation26(void);
13
+ void Init_cs__assess_string_interpolation(void);
@@ -97,9 +97,10 @@ VALUE contrast_register_singleton_prepend_patch(const char *module_name,
97
97
  /* module name c_char "Module"; */
98
98
  /* method name c_char "method"; */
99
99
  /* c_func => pointer */
100
- VALUE contrast_check_and_register_instance_patch(
101
- const char *module_name, const char *method_name,
102
- VALUE(c_fn)(const int, VALUE *, const VALUE)) {
100
+ VALUE contrast_check_and_register_instance_patch(const char *module_name,
101
+ const char *method_name,
102
+ VALUE(c_fn)(const int, VALUE *,
103
+ const VALUE)) {
103
104
 
104
105
  VALUE object, method, is_prepended, patch_type;
105
106
  /* check if method is prepended */
@@ -291,5 +292,5 @@ void Init_cs__common(void) {
291
292
  contrast_check_prepended, 2);
292
293
  /* defined for object lookout */
293
294
  rb_define_singleton_method(assess, "cs__object_method_prepended?",
294
- contrast_lookout_prepended, 4);
295
+ contrast_lookout_prepended, 3);
295
296
  }
@@ -222,19 +222,12 @@ VALUE contrast_run_patches(const VALUE *wrapped_args) {
222
222
  * call site. This means the rest of this function is not executed.
223
223
  */
224
224
 
225
- /* Invoke Contrast post-call patching.
226
- * Post-call patching may transform the return value,
227
- * hence the assignment.
228
- */
229
- transformed_ret = contrast_call_post_patch(method_policy, preshift, object,
225
+ /* Invoke Contrast post-call patching. */
226
+ contrast_call_post_patch(method_policy, preshift, object,
230
227
  original_ret, argc, argv);
231
228
 
232
229
  /* Special case for tracking frozen sources */
233
- if (transformed_ret != Qnil) {
234
- return transformed_ret;
235
- } else {
236
- return original_ret;
237
- }
230
+ return original_ret;
238
231
  }
239
232
 
240
233
  VALUE contrast_ensure_function(const VALUE method_policy) {
@@ -56,18 +56,8 @@ module Contrast
56
56
 
57
57
  # Probably only for source events, but we'll go with source_type instead. java & .net support source_type
58
58
  # in propagation events, so we'll future proof this
59
- def build_event_source_dtm
60
- # You can have a source w/o a name, but not w/o a type
61
- return unless source_type
62
-
63
- dtm = Contrast::Api::Dtm::TraceEventSource.new
64
- dtm.type = forced_source_type
65
- dtm.name = forced_source_name
66
- dtm
67
- end
68
-
69
- # Probably only for source events, but we'll go with source_type instead. java & .net support source_type
70
- # in propagation events, so we'll future proof this
59
+ #
60
+ # @return [Contrast::Agent::Reporting::TraceEventSource, nil]
71
61
  def build_event_source
72
62
  # You can have a source w/o a name, but not w/o a type
73
63
  return unless source_type
@@ -89,6 +79,20 @@ module Contrast
89
79
  event_dtm.target = @policy_node.target_string
90
80
  @policy_node.targets[0]
91
81
  end
82
+
83
+ private
84
+
85
+ # Probably only for source events, but we'll go with source_type instead. java & .net support source_type
86
+ # in propagation events, so we'll future proof this
87
+ def build_event_source_dtm
88
+ # You can have a source w/o a name, but not w/o a type
89
+ return unless source_type
90
+
91
+ dtm = Contrast::Api::Dtm::TraceEventSource.new
92
+ dtm.type = forced_source_type
93
+ dtm.name = forced_source_name
94
+ dtm
95
+ end
92
96
  end
93
97
  end
94
98
  end
@@ -5,6 +5,7 @@ require 'contrast/agent/patching/policy/policy_node'
5
5
  require 'contrast/api/decorators/trace_taint_range_tags'
6
6
  require 'contrast/utils/object_share'
7
7
  require 'contrast/agent/assess/policy/policy_node_utils'
8
+ require 'contrast/components/logger'
8
9
 
9
10
  module Contrast
10
11
  module Agent
@@ -13,6 +14,7 @@ module Contrast
13
14
  # This class functions to translate our policy.json into an actionable
14
15
  # Ruby object, allowing for dynamic patching over hardcoded patching.
15
16
  class PolicyNode < Contrast::Agent::Patching::Policy::PolicyNode
17
+ include Contrast::Components::Logger::InstanceMethods
16
18
  include PolicyNodeUtils
17
19
  JSON_TAGS = 'tags'
18
20
  JSON_DATAFLOW = 'dataflow'
@@ -107,12 +109,16 @@ module Contrast
107
109
  def validate
108
110
  super
109
111
  validate_tags
112
+ rescue ArgumentError => e
113
+ logger.debug('Validation of policy node failed with: ', e)
114
+ nil
110
115
  end
111
116
 
112
117
  # TeamServer is picky. The tags here match to ENUMs there. If there
113
118
  # isn't a matching ENUM in TS land, the database gets got. We really
114
119
  # don't want to get them, so we're going to prevent the node from being
115
120
  # made.
121
+ # @raise[ArgumentError] raises if any of the tags is invalid
116
122
  def validate_tags
117
123
  return unless tags
118
124
 
@@ -58,8 +58,6 @@ module Contrast
58
58
  # ret [Object] the Return of the invoked method
59
59
  # args [Array<Object>] the Arguments with which the method was invoked
60
60
  # @param block [Block] the Block passed to the original method
61
- # @return [Object, nil] the tracked Return or nil if no changes were made; will replace the return of the
62
- # original function if not nil
63
61
  def apply_propagator propagation_node, preshift, target, propagation_data, block
64
62
  return unless propagation_possible?(propagation_node, target)
65
63
 
@@ -133,16 +131,6 @@ module Contrast
133
131
  true
134
132
  end
135
133
 
136
- # Safely duplicate the target, or return nil
137
- #
138
- # @param target [Object] the thing to check for duplication
139
- # @return [Object, nil]
140
- def safe_dup target
141
- target.dup
142
- rescue StandardError => _e
143
- nil
144
- end
145
-
146
134
  # Iterate over each key and value in a hash to allow for propagation to each.
147
135
  #
148
136
  # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
@@ -199,25 +187,11 @@ module Contrast
199
187
  return unless can_propagate?(propagation_node, preshift, target)
200
188
  return unless (propagation_class = find_propagation_class(propagation_node))
201
189
 
202
- restore_frozen_state = false
203
- if target.cs__frozen? && !Contrast::Agent::Assess::Tracker.trackable?(target)
204
- return unless can_handle_frozen?(propagation_node)
205
- return unless (dup = safe_dup(propagation_data.ret))
206
-
207
- restore_frozen_state = true
208
- ret = dup
209
- target = ret
210
- Contrast::Agent::Assess::Tracker.pre_freeze(ret)
211
- ret.cs__freeze
212
- # double check that we were able to finalize the replaced return
213
- return unless Contrast::Agent::Assess::Tracker.trackable?(target)
214
- end
215
-
216
190
  # If we are using the original object tracking, the preshift object is not created.
217
191
  # Instead identify the source as the original object itself and propagate with it.
218
192
  source = propagation_node.use_original_object? ? propagation_data.object : preshift
219
193
  handle_propagation(propagation_class, propagation_node, source, target)
220
- update_properties(restore_frozen_state, propagation_node, target, propagation_data, ret)
194
+ update_properties(propagation_node, target, propagation_data)
221
195
  end
222
196
 
223
197
  def handle_propagation propagation_class, propagation_node, source, target
@@ -228,7 +202,7 @@ module Contrast
228
202
  end
229
203
  end
230
204
 
231
- def update_properties restore_frozen_state, propagation_node, target, propagation_data, ret
205
+ def update_properties propagation_node, target, propagation_data
232
206
  if propagation_node.use_original_on_bang_method?
233
207
  properties = use_original_object_properties(propagation_data)
234
208
 
@@ -248,11 +222,10 @@ module Contrast
248
222
  event_data = Contrast::Agent::Assess::Events::EventData.new(propagation_node,
249
223
  target,
250
224
  propagation_data.object,
251
- ret,
225
+ propagation_data.ret,
252
226
  propagation_data.args)
253
227
  properties.build_event(event_data)
254
228
  logger.trace('Propagation detected', node_id: propagation_node.id, target_id: target.__id__)
255
- restore_frozen_state ? ret : nil
256
229
  end
257
230
 
258
231
  # Find the propagation class from the given node, if one exists.
@@ -269,17 +242,6 @@ module Contrast
269
242
  propagation_class
270
243
  end
271
244
 
272
- # We can handle frozen propagation iff we're allowed to, as determined by configuration, and the target of
273
- # the propagation is a return, as that's a replaceable value.
274
- #
275
- # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs a
276
- # propagation event.
277
- # @return [Boolean]
278
- def can_handle_frozen? propagation_node
279
- ::Contrast::ASSESS.track_frozen_sources? &&
280
- propagation_node.targets[0] == Contrast::Utils::ObjectShare::RETURN_KEY
281
- end
282
-
283
245
  # For certain bang methods we return the same object, no need to create expensive new properties.
284
246
  #
285
247
  # @param propagation_data [Contrast::Agent::Assess::Events::EventData] used to hold object, args
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'contrast/agent/assess/policy/policy_node'
5
5
  require 'contrast/api/decorators/trace_taint_range_tags'
6
+ require 'contrast/components/logger'
6
7
 
7
8
  module Contrast
8
9
  module Agent
@@ -14,6 +15,8 @@ module Contrast
14
15
  # untrusted data (indicate points in the application where user
15
16
  # controlled input is modified).
16
17
  class PropagationNode < PolicyNode
18
+ include Contrast::Components::Logger::InstanceMethods
19
+
17
20
  JSON_ACTION = 'action'
18
21
  JSON_UNTAGS = 'untags'
19
22
  JSON_PATCH_CLASS = 'patch_class'
@@ -41,6 +44,9 @@ module Contrast
41
44
  @patch_method = propagation_hash[JSON_PATCH_METHOD]
42
45
  @patch_method = @patch_method.to_sym if @patch_method
43
46
  validate
47
+ rescue ArgumentError => e
48
+ logger.error('Propagation Node Initialization failed with: ', e)
49
+ nil
44
50
  end
45
51
 
46
52
  def node_class
@@ -56,6 +62,7 @@ module Contrast
56
62
 
57
63
  # Standard validation + TS trace version two rules:
58
64
  # Must have source, target, and action
65
+ # @raise[ArgumentError] raises if any of the required propagation node field is not valid, or is missing
59
66
  def validate
60
67
  super
61
68
  raise(ArgumentError, "Propagator #{ id } did not have a proper action. Unable to create.") unless action
@@ -78,6 +85,7 @@ module Contrast
78
85
  validate_untags
79
86
  end
80
87
 
88
+ # @raise[ArgumentError] raises if any of the tags is invalid
81
89
  def validate_untags
82
90
  return unless untags
83
91
 
@@ -25,6 +25,8 @@ module Contrast
25
25
  Contrast::Agent::Assess::Tracker.tracked?(value)
26
26
  end
27
27
 
28
+ # @raise [NoMethodError] This is being raised if any of the implementing subclasses does not have
29
+ # that method implemented, but is being called on.
28
30
  def propagate _propagation_node, _preshift, _target
29
31
  raise(NoMethodError("Expected Base propagator subclass: #{ cs__class } to implement #propagate"))
30
32
  end
@@ -35,30 +35,17 @@ module Contrast
35
35
  # @param object [Object] the Object on which the method was invoked
36
36
  # @param ret [Object] the Return of the invoked method
37
37
  # @param args [Array<Object>] the Arguments with which the method was invoked
38
- # @return [Object, nil] the tracked Return or nil if no changes were made
39
38
  def apply_source method_policy, object, ret, args
40
39
  return unless analyze?(method_policy, object, ret, args)
41
40
  return unless (source_node = method_policy.source_node)
42
41
 
43
42
  # used to hold the object and ret
44
43
  source_data = Contrast::Agent::Assess::Events::EventData.new(nil, nil, object, ret, nil)
45
- return unless (target = determine_target(source_node, source_data, args))
46
-
47
- return_val = nil
48
- if target.cs__frozen? && !Contrast::Agent::Assess::Tracker.trackable?(target)
49
- return unless ::Contrast::ASSESS.track_frozen_sources?
50
- return unless source_node.targets[0] == Contrast::Utils::ObjectShare::RETURN_KEY
51
- return unless (dup = safe_dup(source_data.ret))
52
- return unless Contrast::Agent::Assess::Tracker.trackable?(dup)
53
44
 
54
- Contrast::Agent::Assess::Tracker.pre_freeze(dup)
55
- return_val = dup.cs__freeze
56
- target = dup
57
- end
45
+ return unless (target = determine_target(source_node, source_data, args))
46
+ return if target.cs__frozen? && !Contrast::Agent::Assess::Tracker.trackable?(target)
58
47
 
59
48
  process_source(source_node, target, source_data, source_node.type, nil, *args)
60
-
61
- return_val
62
49
  end
63
50
  Contrast::Components::Logger.add_trace_log_timing_for(SourceMethod, :apply_source)
64
51
 
@@ -108,42 +95,10 @@ module Contrast
108
95
  # map
109
96
  # @param args [Array<Object>] the Arguments with which the method was invoked
110
97
  def apply_hash_tags source_node, target, source_data, source_type, *args
111
- to_replace = []
112
98
  target.each_pair do |key, value|
113
- # We only do this for Strings b/c of the way Hash lookup works. To replace another object would break
114
- # hash lookup and, therefore, the application
115
- if replace_hash_key?(key, target)
116
- key = key.dup
117
- to_replace << key
118
- end
119
99
  process_source(source_node, key, source_data, key_type(source_type), key, *args)
120
100
  process_source(source_node, value, source_data, source_type, key, *args)
121
101
  end
122
- handle_hash_key(target, to_replace)
123
- end
124
-
125
- # Given an unfrozen hash, if the key is a String, we should replace it with one that we can finalize,
126
- # allowing us to track that key. This method handles checking if that replace can and should occur.
127
- #
128
- # @param key [Object] the key in the hash that may need replacing.
129
- # @param hash [Hash] the hash to which the key belongs.
130
- # @return [Boolean] whether replace the key in the hash or not.
131
- def replace_hash_key? key, hash
132
- ::Contrast::ASSESS.track_frozen_sources? &&
133
- !hash.cs__frozen? &&
134
- key.is_a?(String) &&
135
- !Contrast::Agent::Assess::Tracker.trackable?(key)
136
- end
137
-
138
- # Hash is designed to keep one instance of the string key in it. We need to remove the existing one and
139
- # replace it with our new tracked one.
140
- def handle_hash_key target, to_replace
141
- to_replace.each do |key|
142
- Contrast::Agent::Assess::Tracker.pre_freeze(key)
143
- key.cs__freeze
144
- value = target.delete(key)
145
- target[key] = value
146
- end
147
102
  end
148
103
 
149
104
  # @param source_node [Contrast::Agent::Assess::Policy::SourceNode] the node to direct applying this source
@@ -35,6 +35,7 @@ module Contrast
35
35
 
36
36
  # Standard validation + TS trace version two rules:
37
37
  # Must have source and type
38
+ # @raise[ArgumentError] raises if any of the required fields is missing or invalid
38
39
  def validate
39
40
  super
40
41
  raise(ArgumentError, "Source #{ id } did not have a proper target. Unable to create.") unless targets&.any?
@@ -211,7 +211,7 @@ module Contrast
211
211
 
212
212
  build_events(finding, properties.event) if properties.event
213
213
 
214
- # Google::Protobuf::Map doesn't support merge!, so we have to do this long form
214
+ # CSGoogle::Protobuf::Map doesn't support merge!, so we have to do this long form
215
215
  source_props = properties.properties
216
216
  return unless source_props
217
217
 
@@ -4,6 +4,7 @@
4
4
  require 'contrast/agent/assess/policy/trigger/reflected_xss'
5
5
  require 'contrast/agent/assess/policy/trigger/xpath'
6
6
  require 'contrast/api/decorators/trace_taint_range_tags'
7
+ require 'contrast/components/logger'
7
8
 
8
9
  module Contrast
9
10
  module Agent
@@ -15,6 +16,8 @@ module Contrast
15
16
  # vulnerability (indicate points in the application where uncontrolled
16
17
  # user input can do damage).
17
18
  class TriggerNode < PolicyNode # rubocop:disable Metrics/ClassLength
19
+ include Contrast::Components::Logger::InstanceMethods
20
+
18
21
  JSON_BAD_VALUE = 'bad_value'
19
22
  JSON_GOOD_VALUE = 'good_value'
20
23
  JSON_DISALLOWED_TAGS = 'disallowed_tags'
@@ -59,6 +62,9 @@ module Contrast
59
62
  @trigger_method = trigger_hash['trigger_method']
60
63
  @trigger_method = @trigger_method.to_sym if @trigger_method
61
64
  validate
65
+ rescue ArgumentError => e
66
+ logger.error('Trigger Node initialization failed with: ', e)
67
+ nil
62
68
  end
63
69
 
64
70
  def node_class
@@ -143,6 +149,7 @@ module Contrast
143
149
 
144
150
  # Standard validation + TS trace version two rules:
145
151
  # Must have source
152
+ # @raise[ArgumentError] raises if any of the required fields is invalid or missing
146
153
  def validate
147
154
  super
148
155
  # If this isn't a dataflow rule, it can't have a source
@@ -172,6 +179,7 @@ module Contrast
172
179
  @disallowed_tags << (VALIDATOR_START + loud_name)
173
180
  end
174
181
 
182
+ # @raise[ArgumentError] raises if any of the tags is invalid
175
183
  def validate_rule_tags tags
176
184
  return unless tags
177
185