contrast-agent 6.1.2 → 6.4.0

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