contrast-agent 4.7.0 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -1
  3. data/.rspec +0 -1
  4. data/.rspec_parallel +6 -0
  5. data/.simplecov +1 -0
  6. data/ext/cs__contrast_patch/cs__contrast_patch.c +0 -1
  7. data/ext/cs__contrast_patch/cs__contrast_patch.h +0 -2
  8. data/lib/contrast/agent/assess/contrast_event.rb +1 -5
  9. data/lib/contrast/agent/assess/finalizers/hash.rb +2 -5
  10. data/lib/contrast/agent/assess/policy/patcher.rb +5 -4
  11. data/lib/contrast/agent/assess/policy/policy.rb +1 -1
  12. data/lib/contrast/agent/assess/policy/policy_scanner.rb +2 -6
  13. data/lib/contrast/agent/assess/policy/preshift.rb +11 -8
  14. data/lib/contrast/agent/assess/policy/propagation_method.rb +102 -59
  15. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +2 -7
  16. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +31 -11
  17. data/lib/contrast/agent/assess/policy/propagator/rack_protection.rb +73 -0
  18. data/lib/contrast/agent/assess/policy/propagator/split.rb +10 -6
  19. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +3 -3
  20. data/lib/contrast/agent/assess/policy/propagator.rb +1 -0
  21. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +6 -7
  22. data/lib/contrast/agent/assess/policy/source_method.rb +18 -22
  23. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +0 -4
  24. data/lib/contrast/agent/assess/policy/trigger_method.rb +61 -86
  25. data/lib/contrast/agent/assess/policy/trigger_node.rb +1 -1
  26. data/lib/contrast/agent/assess/property/evented.rb +2 -1
  27. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +3 -4
  28. data/lib/contrast/agent/at_exit_hook.rb +3 -3
  29. data/lib/contrast/agent/class_reopener.rb +6 -5
  30. data/lib/contrast/agent/disable_reaction.rb +4 -5
  31. data/lib/contrast/agent/exclusion_matcher.rb +2 -7
  32. data/lib/contrast/agent/inventory/database_config.rb +117 -0
  33. data/lib/contrast/agent/inventory/dependency_analysis.rb +2 -6
  34. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +8 -9
  35. data/lib/contrast/agent/inventory/policy/datastores.rb +5 -6
  36. data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
  37. data/lib/contrast/agent/middleware.rb +15 -13
  38. data/lib/contrast/agent/patching/policy/after_load_patch.rb +6 -3
  39. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +21 -16
  40. data/lib/contrast/agent/patching/policy/module_policy.rb +2 -4
  41. data/lib/contrast/agent/patching/policy/patch.rb +13 -8
  42. data/lib/contrast/agent/patching/policy/patch_status.rb +3 -7
  43. data/lib/contrast/agent/patching/policy/patcher.rb +14 -14
  44. data/lib/contrast/agent/patching/policy/policy.rb +2 -4
  45. data/lib/contrast/agent/patching/policy/policy_node.rb +2 -3
  46. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
  47. data/lib/contrast/agent/protect/policy/policy.rb +1 -1
  48. data/lib/contrast/agent/protect/policy/rule_applicator.rb +3 -5
  49. data/lib/contrast/agent/protect/rule/base.rb +10 -10
  50. data/lib/contrast/agent/protect/rule/cmd_injection.rb +4 -5
  51. data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -53
  52. data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -5
  53. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +137 -0
  54. data/lib/contrast/agent/protect/rule/sqli.rb +7 -70
  55. data/lib/contrast/agent/reaction_processor.rb +3 -4
  56. data/lib/contrast/agent/request.rb +9 -5
  57. data/lib/contrast/agent/request_context.rb +28 -31
  58. data/lib/contrast/agent/request_handler.rb +5 -3
  59. data/lib/contrast/agent/response.rb +2 -3
  60. data/lib/contrast/agent/rewriter.rb +4 -3
  61. data/lib/contrast/agent/rule_set.rb +5 -4
  62. data/lib/contrast/agent/service_heartbeat.rb +2 -3
  63. data/lib/contrast/agent/static_analysis.rb +7 -6
  64. data/lib/contrast/agent/thread.rb +2 -4
  65. data/lib/contrast/agent/thread_watcher.rb +3 -4
  66. data/lib/contrast/agent/tracepoint_hook.rb +10 -5
  67. data/lib/contrast/agent/version.rb +1 -1
  68. data/lib/contrast/api/communication/messaging_queue.rb +16 -11
  69. data/lib/contrast/api/communication/response_processor.rb +11 -11
  70. data/lib/contrast/api/communication/service_lifecycle.rb +9 -5
  71. data/lib/contrast/api/communication/socket_client.rb +18 -14
  72. data/lib/contrast/api/communication/speedracer.rb +5 -6
  73. data/lib/contrast/api/decorators/address.rb +2 -3
  74. data/lib/contrast/api/decorators/agent_startup.rb +7 -9
  75. data/lib/contrast/api/decorators/application_startup.rb +9 -10
  76. data/lib/contrast/api/decorators/application_update.rb +0 -4
  77. data/lib/contrast/api/decorators/http_request.rb +3 -7
  78. data/lib/contrast/api/decorators/instrumentation_mode.rb +3 -5
  79. data/lib/contrast/api/decorators/message.rb +7 -7
  80. data/lib/contrast/api/decorators/route_coverage.rb +24 -1
  81. data/lib/contrast/api/decorators/trace_event_object.rb +2 -3
  82. data/lib/contrast/components/agent.rb +13 -15
  83. data/lib/contrast/components/app_context.rb +7 -11
  84. data/lib/contrast/components/assess.rb +19 -16
  85. data/lib/contrast/components/base.rb +40 -0
  86. data/lib/contrast/components/config.rb +1 -2
  87. data/lib/contrast/components/contrast_service.rb +8 -11
  88. data/lib/contrast/components/heap_dump.rb +5 -4
  89. data/lib/contrast/components/inventory.rb +2 -7
  90. data/lib/contrast/components/logger.rb +14 -10
  91. data/lib/contrast/components/protect.rb +10 -13
  92. data/lib/contrast/components/sampling.rb +5 -5
  93. data/lib/contrast/components/scope.rb +9 -32
  94. data/lib/contrast/components/settings.rb +1 -5
  95. data/lib/contrast/config/base_configuration.rb +14 -6
  96. data/lib/contrast/configuration.rb +22 -19
  97. data/lib/contrast/extension/assess/array.rb +3 -15
  98. data/lib/contrast/extension/assess/eval_trigger.rb +2 -23
  99. data/lib/contrast/extension/assess/fiber.rb +6 -16
  100. data/lib/contrast/extension/assess/hash.rb +3 -13
  101. data/lib/contrast/extension/assess/kernel.rb +3 -14
  102. data/lib/contrast/extension/assess/marshal.rb +6 -14
  103. data/lib/contrast/extension/assess/regexp.rb +5 -15
  104. data/lib/contrast/extension/assess/string.rb +6 -31
  105. data/lib/contrast/extension/extension.rb +61 -0
  106. data/lib/contrast/extension/kernel.rb +2 -4
  107. data/lib/contrast/extension/protect/kernel.rb +0 -15
  108. data/lib/contrast/framework/grape/support.rb +174 -0
  109. data/lib/contrast/framework/manager.rb +44 -9
  110. data/lib/contrast/framework/rack/patch/session_cookie.rb +6 -6
  111. data/lib/contrast/framework/rack/support.rb +1 -1
  112. data/lib/contrast/framework/rails/patch/assess_configuration.rb +5 -8
  113. data/lib/contrast/framework/rails/patch/support.rb +44 -37
  114. data/lib/contrast/framework/rails/railtie.rb +34 -0
  115. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +4 -4
  116. data/lib/contrast/framework/rails/support.rb +60 -13
  117. data/lib/contrast/framework/sinatra/support.rb +1 -1
  118. data/lib/contrast/funchook/funchook.rb +4 -3
  119. data/lib/contrast/logger/application.rb +1 -6
  120. data/lib/contrast/logger/log.rb +103 -13
  121. data/lib/contrast/logger/request.rb +0 -4
  122. data/lib/contrast/tasks/config.rb +0 -1
  123. data/lib/contrast/tasks/service.rb +1 -6
  124. data/lib/contrast/utils/assess/sampling_util.rb +2 -3
  125. data/lib/contrast/utils/assess/tracking_util.rb +2 -4
  126. data/lib/contrast/utils/heap_dump_util.rb +5 -3
  127. data/lib/contrast/utils/invalid_configuration_util.rb +4 -3
  128. data/lib/contrast/utils/io_util.rb +3 -5
  129. data/lib/contrast/utils/job_servers_running.rb +4 -3
  130. data/lib/contrast/utils/os.rb +2 -3
  131. data/lib/contrast/utils/ruby_ast_rewriter.rb +16 -13
  132. data/lib/contrast/utils/string_utils.rb +2 -3
  133. data/lib/contrast/utils/tag_util.rb +26 -19
  134. data/lib/contrast.rb +24 -14
  135. data/resources/assess/policy.json +252 -2
  136. data/resources/deadzone/policy.json +10 -0
  137. data/ruby-agent.gemspec +14 -3
  138. data/service_executables/VERSION +1 -1
  139. data/service_executables/linux/contrast-service +0 -0
  140. data/service_executables/mac/contrast-service +0 -0
  141. metadata +104 -24
  142. data/lib/contrast/agent/railtie.rb +0 -31
  143. data/lib/contrast/components/interface.rb +0 -196
  144. data/lib/contrast/delegators/input_analysis.rb +0 -12
  145. data/lib/contrast/utils/inventory_util.rb +0 -114
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b3d1ce6b9794d3923d2054d9a20bd31989fd0c6b4df2883f81ad3e740c04de5
4
- data.tar.gz: 894505c04e850858f83e2207c52cc944f738ce19183051d9530cfdaf09f72ab7
3
+ metadata.gz: ab65fd574ef84fbe339e4f4d4bf340623235a442ecc11d7ba28c6af3c6f04d4d
4
+ data.tar.gz: 0fa9cc44fe85713ee924101139e615d361de6d906c8f5ff4fdd345a930eee9d2
5
5
  SHA512:
6
- metadata.gz: 4df81e8b3d03efcdc952e9fce5330b34c6af6a965701ec7bbe02cf3dbd5b8a3c98d8d0745da91d7b0a43be6b03ac763ffb6e9eafb9f2b857bd2a76d325d10ad2
7
- data.tar.gz: 0015e74007146cf741e6b7f6274460a948a147df54109de959856f0ff883262260685f74eff8767e6ae845847eaf3d8a17dfbd54061d5b9f561952a8c6b90fef
6
+ metadata.gz: cb21ebcad0e772649d16a25d2f00cc057ee10df71638b7bd7cc6a4710a1ded28ce4dca749fa040ba2fb78e992727f4cc5d5f38e1187c363a8ea33a12333fc289
7
+ data.tar.gz: c3ad4c82a9e25ecb58c0ea906f1170cffdd6811952f9c1d71a6c75166358a37e0ebba40e55e9a7433156a51122b9ca1450bb5a4a2a87f9081a4a4268d9abfdb4
data/.gitignore CHANGED
@@ -1,8 +1,8 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /_yardoc/
4
- /Gemfile.lock
5
4
  /coverage/
5
+ /Gemfile.lock
6
6
  /data/*
7
7
  /doc/
8
8
  /log/
@@ -18,6 +18,11 @@
18
18
  /ext/**/*.so
19
19
  /ext/**/*.bundle
20
20
 
21
+ bin
22
+ ruby-spec
23
+ mspec
24
+ service_executables
25
+
21
26
  # Funchook artifacts
22
27
  /ext/**/funchook.h
23
28
  /ext/**/libfunchook.dylib
data/.rspec CHANGED
@@ -3,4 +3,3 @@
3
3
  --format documentation
4
4
  --format RspecJunitFormatter
5
5
  --out ./test-results/results.xml
6
- --color
data/.rspec_parallel ADDED
@@ -0,0 +1,6 @@
1
+ --require spec_helper
2
+ --order rand
3
+ --format progress
4
+ --format RspecJunitFormatter
5
+ --out ./test-results/results.xml
6
+ --format ParallelTests::RSpec::FailuresLogger --out tmp/failing_specs.log
data/.simplecov CHANGED
@@ -4,4 +4,5 @@
4
4
  SimpleCov.minimum_coverage line: 94.75
5
5
  SimpleCov.start do
6
6
  add_filter '/spec/'
7
+ enable_coverage :branch
7
8
  end
@@ -437,7 +437,6 @@ void Init_cs__contrast_patch(void) {
437
437
  rb_sym_contrast_apply_pre_patch = rb_intern("apply_pre_patch");
438
438
  rb_sym_cs_to_s = rb_intern("to_s");
439
439
  rb_sym_custom_patch = rb_intern("requires_custom_patch?");
440
- rb_sym_in_request_context = rb_intern("in_request_context?");
441
440
  rb_sym_info_for = rb_intern("info_for");
442
441
  rb_sym_propagation_node = rb_intern("propagation_node");
443
442
  rb_sym_set_info_for = rb_intern("set_info_for");
@@ -16,8 +16,6 @@ static VALUE rb_sym_contrast_apply_pre_patch;
16
16
  static VALUE rb_sym_custom_patch;
17
17
  static VALUE rb_sym_cs_to_s;
18
18
 
19
- static VALUE rb_sym_in_request_context;
20
-
21
19
  static VALUE rb_sym_enter_method_scope;
22
20
  static VALUE rb_sym_exit_method_scope;
23
21
 
@@ -8,7 +8,6 @@ require 'contrast/utils/object_share'
8
8
  require 'contrast/utils/stack_trace_utils'
9
9
  require 'contrast/utils/string_utils'
10
10
  require 'contrast/utils/timer'
11
- require 'contrast/components/interface'
12
11
  require 'contrast/agent/assess/contrast_object'
13
12
 
14
13
  module Contrast
@@ -29,9 +28,6 @@ module Contrast
29
28
  # @attr_reader args [Array<Contrast::Agent::Assess::ContrastObject>] the safe representation of the Arguments
30
29
  # with which the method was invoked
31
30
  class ContrastEvent
32
- include Contrast::Components::Interface
33
- access_component :analysis
34
-
35
31
  attr_reader :event_id, :policy_node, :stack_trace, :time, :thread, :object, :ret, :args, :tags
36
32
 
37
33
  # We need this to track the parent id's of events to build up a flow chart of the finding
@@ -164,7 +160,7 @@ module Contrast
164
160
  def capture_stacktrace!
165
161
  # If we're configured to not capture the stacktrace, usually for performance reasons, then don't and return an
166
162
  # empty array instead
167
- unless ASSESS.capture_stacktrace?(policy_node)
163
+ unless ::Contrast::ASSESS.capture_stacktrace?(policy_node)
168
164
  @stack_trace = Contrast::Utils::ObjectShare::EMPTY_ARRAY
169
165
  return
170
166
  end
@@ -10,13 +10,10 @@ module Contrast
10
10
  # An extension of Hash that doesn't impact GC of the object being stored by storing its ID as a Key to lookup
11
11
  # and registering a finalizer on the object to remove its entry from the Hash immediately after it's GC'd.
12
12
  class Hash < Hash
13
- include Contrast::Components::Interface
14
- access_component :agent, :analysis
15
-
16
13
  FROZEN_FINALIZED_IDS = Set.new
17
14
 
18
15
  def []= key, obj
19
- return unless AGENT.enabled? && ASSESS.enabled?
16
+ return unless ::Contrast::AGENT.enabled? && ::Contrast::ASSESS.enabled?
20
17
 
21
18
  # We can't finalize frozen things, so only act on those that went through .pre_freeze
22
19
  if key.cs__frozen?
@@ -79,7 +76,7 @@ module Contrast
79
76
  #
80
77
  # @param key [Object] the Object on which we need to pre-define finalizers
81
78
  def pre_freeze key
82
- return unless AGENT.enabled? && ASSESS.enabled?
79
+ return unless ::Contrast::AGENT.enabled? && ::Contrast::ASSESS.enabled?
83
80
  return if key.cs__frozen?
84
81
  return if FROZEN_FINALIZED_IDS.include?(key.__id__)
85
82
 
@@ -5,7 +5,8 @@ require 'contrast/agent/assess/policy/policy'
5
5
  require 'contrast/agent/patching/policy/patcher'
6
6
  require 'contrast/agent/patching/policy/method_policy'
7
7
  require 'contrast/agent/patching/policy/module_policy'
8
- require 'contrast/components/interface'
8
+ require 'contrast/components/logger'
9
+ require 'contrast/components/scope'
9
10
 
10
11
  module Contrast
11
12
  module Agent
@@ -16,8 +17,8 @@ module Contrast
16
17
  # provides a map for which methods our renamed functions need to call
17
18
  # and how.
18
19
  module Patcher
19
- include Contrast::Components::Interface
20
- access_component :logging, :analysis, :agent, :scope
20
+ extend Contrast::Components::Logger::InstanceMethods
21
+ extend Contrast::Components::Scope::InstanceMethods
21
22
 
22
23
  class << self
23
24
  def policy
@@ -34,7 +35,7 @@ module Contrast
34
35
  # called. This hook is provided so that patches to those methods can
35
36
  # pass us execution flow once a new method has been made available.
36
37
  def patch_assess_on_eval mod
37
- return unless ASSESS.enabled?
38
+ return unless ::Contrast::ASSESS.enabled?
38
39
  return if in_contrast_scope?
39
40
 
40
41
  patcher.patch_specific_module(mod)
@@ -26,7 +26,7 @@ module Contrast
26
26
  # Indicates is this feature has been disabled by the configuration,
27
27
  # read at startup, and therefore can never be enabled.
28
28
  def disabled_globally?
29
- ASSESS.forcibly_disabled?
29
+ ::Contrast::ASSESS.forcibly_disabled?
30
30
  end
31
31
 
32
32
  def node_type
@@ -1,7 +1,6 @@
1
1
  # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/components/interface'
5
4
  require 'contrast/utils/object_share'
6
5
 
7
6
  module Contrast
@@ -13,9 +12,6 @@ module Contrast
13
12
  # of a file vs data flow, such as the detection of Hardcoded Passwords
14
13
  # or Keys.
15
14
  module PolicyScanner
16
- include Contrast::Components::Interface
17
- access_component :analysis
18
-
19
15
  class << self
20
16
  # Use the given trace_point, built from an :end event, to determine
21
17
  # where the loaded code lives and scan that code for policy
@@ -24,8 +20,8 @@ module Contrast
24
20
  # @param trace_point [TracePoint] the TracePoint generated by an
25
21
  # :end event at the end of a Module definition.
26
22
  def scan trace_point
27
- return unless ASSESS.enabled?
28
- return unless ASSESS.require_scan?
23
+ return unless ::Contrast::ASSESS.enabled?
24
+ return unless ::Contrast::ASSESS.require_scan?
29
25
 
30
26
  provider_values = policy.providers.values
31
27
  return if provider_values.all?(&:disabled?)
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/components/interface'
4
+ require 'contrast/components/logger'
5
5
 
6
6
  module Contrast
7
7
  module Agent
@@ -9,8 +9,8 @@ module Contrast
9
9
  # In order to properly shift tags to account for the changes this method
10
10
  # caused, we'll need to store the state before the change occurred.
11
11
  class PreShift
12
- include Contrast::Components::Interface
13
- access_component :analysis, :logging
12
+ include Contrast::Components::Logger::InstanceMethods
13
+ extend Contrast::Components::Logger::InstanceMethods
14
14
 
15
15
  UNDUPLICABLE_MODULES = [
16
16
  Enumerator # dup'ing results in 'can't copy execution context'
@@ -37,7 +37,7 @@ module Contrast
37
37
  # being called or nil if one is not required.
38
38
  def build_preshift propagation_node, object, args
39
39
  return unless propagation_node
40
- return unless ASSESS.enabled?
40
+ return unless ::Contrast::ASSESS.enabled?
41
41
 
42
42
  initializing = propagation_node.method_name == :initialize
43
43
  return if unsafe_io_object?(object, initializing)
@@ -84,12 +84,15 @@ module Contrast
84
84
 
85
85
  def append_arg_details preshift, args
86
86
  preshift.args = args.dup
87
- preshift.args.each_with_index do |preshift_arg, index|
88
- original_arg = args[index]
89
- next if preshift_arg.__id__ == original_arg.__id__
87
+ idx = 0
88
+ while idx < preshift.args.size
89
+ original_arg = args[idx]
90
+ p_arg = preshift.args[idx]
91
+ idx += 1
92
+ next if p_arg.__id__ == original_arg.__id__
90
93
  next unless Contrast::Agent::Assess::Tracker.tracked?(original_arg)
91
94
 
92
- Contrast::Agent::Assess::Tracker.copy(original_arg, preshift_arg)
95
+ Contrast::Agent::Assess::Tracker.copy(original_arg, p_arg)
93
96
  end
94
97
  preshift.arg_lengths = preshift.args.map do |preshift_arg|
95
98
  Contrast::Utils::DuckUtils.quacks_to?(preshift_arg, :length) ? preshift_arg.length : 0
@@ -4,7 +4,7 @@
4
4
  require 'set'
5
5
 
6
6
  require 'contrast/agent/assess/policy/propagator'
7
- require 'contrast/components/interface'
7
+ require 'contrast/components/logger'
8
8
  require 'contrast/utils/object_share'
9
9
  require 'contrast/utils/sha256_builder'
10
10
 
@@ -12,13 +12,10 @@ module Contrast
12
12
  module Agent
13
13
  module Assess
14
14
  module Policy
15
- # This class is responsible for the continuation of traces. A
16
- # Propagator is any method that transforms an untrusted value. In
17
- # general, these methods work on the String class or a holder of
18
- # Strings
15
+ # This class is responsible for the continuation of traces. A Propagator is any method that transforms an
16
+ # untrusted value. In general, these methods work on the String class or a holder of Strings.
19
17
  module PropagationMethod
20
- include Contrast::Components::Interface
21
- access_component :analysis, :logging
18
+ extend Contrast::Components::Logger::InstanceMethods
22
19
 
23
20
  APPEND_ACTION = 'APPEND'
24
21
  CENTER_ACTION = 'CENTER'
@@ -48,19 +45,16 @@ module Contrast
48
45
  end
49
46
  end
50
47
 
51
- # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy]
52
- # the policy that governs the patches to this method
53
- # @param preshift [Contrast::Agent::Assess::PreShift] The capture
54
- # of the state of the code just prior to the invocation of the
55
- # patched method.
48
+ # @param method_policy [Contrast::Agent::Patching::Policy::MethodPolicy] the policy that governs the
49
+ # patches to this method
50
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
51
+ # the invocation of the patched method.
56
52
  # @param object [Object] the Object on which the method was invoked
57
53
  # @param ret [Object] the Return of the invoked method
58
- # @param args [Array<Object>] the Arguments with which the method
59
- # was invoked
54
+ # @param args [Array<Object>] the Arguments with which the method was invoked
60
55
  # @param block [Block] the Block passed to the original method
61
- # @return [Object, nil] the tracked Return or nil if no changes
62
- # were made; will replace the return of the original function if
63
- # not nil
56
+ # @return [Object, nil] the tracked Return or nil if no changes were made; will replace the return of the
57
+ # original function if not nil
64
58
  def apply_propagation method_policy, preshift, object, ret, args, block
65
59
  return unless method_policy.propagation_node
66
60
  return unless preshift
@@ -86,26 +80,21 @@ module Contrast
86
80
  SPLIT_ACTION => Contrast::Agent::Assess::Policy::Propagator::Split
87
81
  }.cs__freeze
88
82
 
89
- # I lied above. We had to figure out what the target of the
90
- # propagation was. Now that we know, we'll actually do things to
91
- # it. Note that the return of this method will replace the original
92
- # return of the patched function unless it is nil, so be sure
93
- # you're returning what you intend.
83
+ # I lied above. We had to figure out what the target of the propagation was. Now that we know, we'll
84
+ # actually do things to it. Note that the return of this method will replace the original return of the
85
+ # patched function unless it is nil, so be sure you're returning what you intend.
94
86
  #
95
- # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
96
- # the node that governs this propagation event.
97
- # @param preshift [Contrast::Agent::Assess::PreShift] The capture
98
- # of the state of the code just prior to the invocation of the
99
- # patched method.
87
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
88
+ # propagation event.
89
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
90
+ # the invocation of the patched method.
100
91
  # @param target [Object] the Target to which to propagate.
101
92
  # @param object [Object] the Object on which the method was invoked
102
93
  # @param ret [Object] the Return of the invoked method
103
- # @param args [Array<Object>] the Arguments with which the method
104
- # was invoked
94
+ # @param args [Array<Object>] the Arguments with which the method was invoked
105
95
  # @param block [Block] the Block passed to the original method
106
- # @return [Object, nil] the tracked Return or nil if no changes
107
- # were made; will replace the return of the original function if
108
- # not nil
96
+ # @return [Object, nil] the tracked Return or nil if no changes were made; will replace the return of the
97
+ # original function if not nil
109
98
  def apply_propagator propagation_node, preshift, target, object, ret, args, block
110
99
  return unless propagation_possible?(propagation_node, target)
111
100
 
@@ -127,13 +116,16 @@ module Contrast
127
116
  nil
128
117
  end
129
118
 
130
- # Custom actions tend to be the more complex of our propagations.
131
- # Often, the method has to make decisions about the target based on
132
- # the context with which the method was called. As such, defer
133
- # determining if the target is valid to that method.
119
+ # Custom actions tend to be the more complex of our propagations. Often, the method has to make decisions
120
+ # about the target based on the context with which the method was called. As such, defer determining if the
121
+ # target is valid to that method.
122
+ #
123
+ # In all other cases, a target is valid for propagation if it is not nil
134
124
  #
135
- # In all other cases, a target is valid for propagation if it is not
136
- # nil
125
+ # @param target [Object] the thing to which to propagate
126
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
127
+ # propagation event.
128
+ # @return [Boolean]
137
129
  def valid_target? target, propagation_node
138
130
  return true if propagation_node.action == CUSTOM_ACTION
139
131
 
@@ -141,8 +133,11 @@ module Contrast
141
133
  end
142
134
 
143
135
  ZERO_LENGTH_ACTIONS = [DB_WRITE_ACTION, CUSTOM_ACTION, KEEP_ACTION, REPLACE_ACTION, SPLAT_ACTION].cs__freeze
144
- # If the action required needs a length and the target does not have
145
- # one, the length is not valid
136
+ # If the action required needs a length and the target does not have one, the length is not valid
137
+ #
138
+ # @param target [Object] the thing to which to propagate
139
+ # @param action [String] the name of the action taken during this propagation
140
+ # @return [Boolean]
146
141
  def valid_length? target, action
147
142
  return true if ZERO_LENGTH_ACTIONS.include?(action)
148
143
 
@@ -153,9 +148,15 @@ module Contrast
153
148
  end
154
149
  end
155
150
 
156
- # Before we do any work, we should check if we even need to.
157
- # If the source of this patcher is not tracked, there's no need to do
158
- # anything. A copy of nothing is still nothing.
151
+ # Before we do any work, we should check if we even need to. If the source and target of this patcher are
152
+ # not tracked, there's no need to do anything. A copy of nothing is still nothing.
153
+ #
154
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
155
+ # propagation event.
156
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
157
+ # the invocation of the patched method.
158
+ # @param target [Object] the thing to which to propagate
159
+ # @return [Boolean]
159
160
  def can_propagate? propagation_node, preshift, target
160
161
  return false unless appropriate_target?(propagation_node, target)
161
162
  return true if Contrast::Utils::Assess::TrackingUtil.tracked?(target)
@@ -165,22 +166,21 @@ module Contrast
165
166
  case source
166
167
  when Contrast::Utils::ObjectShare::OBJECT_KEY
167
168
  return true if Contrast::Utils::Assess::TrackingUtil.tracked?(preshift.object)
168
- else # has to be P, there's no ret source type (yet? ever?)
169
+ else
170
+ # has to be P, there's no ret source type (yet? ever?)
169
171
  return true if preshift.args && Contrast::Utils::Assess::TrackingUtil.tracked?(preshift.args[source])
170
172
  end
171
173
  end
172
174
  false
173
175
  end
174
176
 
175
- # We cannot propagate to frozen things that have not been updated
176
- # to work with our property tracking, unless they're duplicable and
177
- # the return.
178
- # We probably shouldn't propagate to frozen things at all, as
179
- # they're supposed to be immutable, but third parties do jenky
180
- # things, so allow it as long as it is safe to do.
177
+ # We cannot propagate to frozen things that have not been updated to work with our property tracking,
178
+ # unless they're duplicable and the return. We probably shouldn't propagate to frozen things at all, as
179
+ # they're supposed to be immutable, but third parties do jenky things, so allow it as long as it is safe to
180
+ # do.
181
181
  #
182
- # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
183
- # the node that governs this propagation event.
182
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
183
+ # propagation event.
184
184
  # @param target [Object] the Target to which to propagate.
185
185
  # @return [Boolean] if the target can be propagated to
186
186
  def appropriate_target? propagation_node, target
@@ -191,6 +191,9 @@ module Contrast
191
191
  end
192
192
 
193
193
  # If this patcher has tags, apply them to the entire target
194
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
195
+ # propagation event.
196
+ # @param target [Object] the Target to which to propagate.
194
197
  def apply_tags propagation_node, target
195
198
  return unless propagation_node.tags
196
199
  return unless (properties = Contrast::Agent::Assess::Tracker.properties(target))
@@ -202,6 +205,10 @@ module Contrast
202
205
  end
203
206
 
204
207
  # If this patcher has tags, remove them from the entire target
208
+ #
209
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
210
+ # propagation event.
211
+ # @param target [Object] the Target to which to propagate.
205
212
  def apply_untags propagation_node, target
206
213
  return unless propagation_node.untags
207
214
  return unless (properties = Contrast::Agent::Assess::Tracker.properties(target))
@@ -214,6 +221,10 @@ module Contrast
214
221
  private
215
222
 
216
223
  # This is checked right before actual propagation
224
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
225
+ # propagation event.
226
+ # @param target [Object] the Target to which to propagate.
227
+ # @return [Boolean]
217
228
  def propagation_possible? propagation_node, target
218
229
  return false unless propagation_node && valid_target?(target, propagation_node)
219
230
  return false unless valid_length?(target, propagation_node.action)
@@ -224,12 +235,24 @@ module Contrast
224
235
  # Safely duplicate the target, or return nil
225
236
  #
226
237
  # @param target [Object] the thing to check for duplication
238
+ # @return [Object, nil]
227
239
  def safe_dup target
228
240
  target.dup
229
241
  rescue StandardError => _e
230
242
  nil
231
243
  end
232
244
 
245
+ # Iterate over each key and value in a hash to allow for propagation to each.
246
+ #
247
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
248
+ # propagation event.
249
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
250
+ # the invocation of the patched method.
251
+ # @param target [Object] the Target to which to propagate.
252
+ # @param object [Object] the Object on which the method was invoked
253
+ # @param ret [Object] the Return of the invoked method
254
+ # @param args [Array<Object>] the Arguments with which the method was invoked
255
+ # @param block [Block] the Block passed to the original method
233
256
  def handle_hash_propagation propagation_node, preshift, target, object, ret, args, block
234
257
  target.each_pair do |key, value|
235
258
  apply_propagator(propagation_node, preshift, key, object, ret, args, block)
@@ -237,6 +260,17 @@ module Contrast
237
260
  end
238
261
  end
239
262
 
263
+ # Iterate over each value in an enumerable to allow for propagation to each.
264
+ #
265
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
266
+ # propagation event.
267
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
268
+ # the invocation of the patched method.
269
+ # @param target [Object] the Target to which to propagate.
270
+ # @param object [Object] the Object on which the method was invoked
271
+ # @param ret [Object] the Return of the invoked method
272
+ # @param args [Array<Object>] the Arguments with which the method was invoked
273
+ # @param block [Block] the Block passed to the original method
240
274
  def handle_enumerable_propagation propagation_node, preshift, target, object, ret, args, block
241
275
  target.each do |value|
242
276
  next if target == value
@@ -245,6 +279,17 @@ module Contrast
245
279
  end
246
280
  end
247
281
 
282
+ # Move the properties from the source(s) to the target of the propagation.
283
+ #
284
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
285
+ # propagation event.
286
+ # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
287
+ # the invocation of the patched method.
288
+ # @param target [Object] the Target to which to propagate.
289
+ # @param object [Object] the Object on which the method was invoked
290
+ # @param ret [Object] the Return of the invoked method
291
+ # @param args [Array<Object>] the Arguments with which the method was invoked
292
+ # @param _block [Block] the Block passed to the original method
248
293
  def handle_cs_properties_propagation propagation_node, preshift, target, object, ret, args, _block
249
294
  return if propagation_node.action == NOOP_ACTION
250
295
  return unless can_propagate?(propagation_node, preshift, target)
@@ -266,12 +311,9 @@ module Contrast
266
311
  propagation_class.propagate(propagation_node, preshift, target)
267
312
  # Once we've propagated, attempt to tag the target if there is a tag(s) to be applied
268
313
  apply_tags(propagation_node, target)
269
- # Even though we skipped propagating tags from the source if they
270
- # were included in untags, the target may have already had some on
271
- # it. Let's go ahead and remove them.
272
- # In this order, untags takes precedent over tags; but we control
273
- # both and there should never be a propagator that has a tag in
274
- # its untag.
314
+ # Even though we skipped propagating tags from the source if they were included in untags, the target may
315
+ # have already had some on it. Let's go ahead and remove them. In this order, untags takes precedent over
316
+ # tags; but we control both and there should never be a propagator that has a tag in its untag.
275
317
  apply_untags(propagation_node, target)
276
318
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
277
319
 
@@ -302,7 +344,8 @@ module Contrast
302
344
  # propagation event.
303
345
  # @return [Boolean]
304
346
  def can_handle_frozen? propagation_node
305
- ASSESS.track_frozen_sources? && propagation_node.targets[0] == Contrast::Utils::ObjectShare::RETURN_KEY
347
+ ::Contrast::ASSESS.track_frozen_sources? &&
348
+ propagation_node.targets[0] == Contrast::Utils::ObjectShare::RETURN_KEY
306
349
  end
307
350
  end
308
351
  end