contrast-agent 7.4.1 → 7.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__common/cs__common.c +5 -5
  3. data/ext/cs__contrast_patch/cs__contrast_patch.c +2 -1
  4. data/ext/cs__scope/cs__scope.c +6 -5
  5. data/lib/contrast/agent/assess/events/event_data.rb +11 -2
  6. data/lib/contrast/agent/assess/finalizers/freeze.rb +1 -0
  7. data/lib/contrast/agent/assess/finalizers/hash.rb +7 -0
  8. data/lib/contrast/agent/assess/policy/patcher.rb +2 -0
  9. data/lib/contrast/agent/assess/policy/policy.rb +4 -0
  10. data/lib/contrast/agent/assess/policy/policy_node.rb +29 -7
  11. data/lib/contrast/agent/assess/policy/preshift.rb +34 -1
  12. data/lib/contrast/agent/assess/policy/propagation_method.rb +16 -1
  13. data/lib/contrast/agent/assess/policy/propagation_node.rb +40 -1
  14. data/lib/contrast/agent/assess/policy/propagator/append.rb +5 -0
  15. data/lib/contrast/agent/assess/policy/propagator/base.rb +10 -0
  16. data/lib/contrast/agent/assess/policy/propagator/buffer.rb +6 -0
  17. data/lib/contrast/agent/assess/policy/propagator/center.rb +14 -0
  18. data/lib/contrast/agent/assess/policy/propagator/custom.rb +6 -0
  19. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +14 -0
  20. data/lib/contrast/agent/assess/policy/propagator/insert.rb +6 -0
  21. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +38 -0
  22. data/lib/contrast/agent/assess/policy/propagator/next.rb +6 -0
  23. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +5 -0
  24. data/lib/contrast/agent/assess/policy/propagator/remove.rb +4 -0
  25. data/lib/contrast/agent/assess/policy/propagator/replace.rb +5 -0
  26. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +5 -0
  27. data/lib/contrast/agent/assess/policy/propagator/select.rb +30 -0
  28. data/lib/contrast/agent/assess/policy/propagator/splat.rb +10 -0
  29. data/lib/contrast/agent/assess/policy/source_node.rb +5 -1
  30. data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +4 -0
  31. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +16 -0
  32. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +19 -0
  33. data/lib/contrast/agent/assess/policy/trigger_method.rb +8 -1
  34. data/lib/contrast/agent/assess/policy/trigger_node.rb +11 -1
  35. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +4 -0
  36. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +6 -0
  37. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +6 -0
  38. data/lib/contrast/agent/hooks/at_exit_hook.rb +17 -1
  39. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +14 -5
  40. data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +0 -26
  41. data/lib/contrast/agent/protect/rule/cmdi/cmd_injection.rb +5 -0
  42. data/lib/contrast/agent/protect/rule/input_classification/base.rb +1 -4
  43. data/lib/contrast/agent/protect/rule/input_classification/encoding.rb +34 -2
  44. data/lib/contrast/agent/reporting/input_analysis/input_type.rb +4 -34
  45. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +1 -1
  46. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -1
  47. data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +4 -4
  48. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -1
  49. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +6 -2
  50. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +3 -3
  51. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +19 -7
  52. data/lib/contrast/agent/request/request_handler.rb +1 -0
  53. data/lib/contrast/agent/version.rb +1 -1
  54. data/lib/contrast/configuration.rb +1 -1
  55. data/lib/contrast/utils/json.rb +1 -1
  56. data/lib/contrast/utils/middleware_utils.rb +9 -0
  57. data/lib/contrast/utils/routes_sent.rb +3 -2
  58. data/lib/contrast.rb +2 -2
  59. data/resources/assess/policy.json +50 -1
  60. data/ruby-agent.gemspec +14 -13
  61. metadata +39 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b62e21b5f8d2c3d786aaaac33005487eab07fd07438e9fe20532742f926bcb0
4
- data.tar.gz: 37ff12d328d1a58bddb75e4f0e9c799b44df881daaa78bea62f565f95ae715ff
3
+ metadata.gz: '089a689fce3dfbc204455c12d29788d316553aa3ff6738fcf515e9f90730a7ae'
4
+ data.tar.gz: 5fc2d10ffc084070fc3c268a9cb05d1f479b48cb16974b2501887cb1b762d6f6
5
5
  SHA512:
6
- metadata.gz: 46f9f576d3a28befa4681e73a250af98602c100d50ace13a1e3fcaa5a22ca2a0d0695b4b19492677d57183ff56203d2f57a5470b7c6fa0fc9c1b15bbbd49dc16
7
- data.tar.gz: 427a3dafa3d8108a4aa2130ff02c8c4d52539f7d1c7b265ba78d60dc10f86f142a2b4f1132ae0be02c0c9a41c043ab1459c0a0e3a836dbced2f0db4b550aa970
6
+ metadata.gz: d13b3205d1e0cb67c8974fdf6d12f78e5a95f2886c59a14439ddc59b9dd8a3b0d0ebd23c5ebfe687d02cf1a12c9b17b127d821ea8131f0876ab284dac62c8b1b
7
+ data.tar.gz: 73932d309fafe50ab5bc962655b58306cd5fae6a64729be1a4159274fe39c55c2138027c30525d07f773966476991685ba9b36cd0820527557d417324225af0d
@@ -28,12 +28,12 @@ void patch_via_funchook(void *original_function, void *hook_function) {
28
28
 
29
29
  void *funchook_lib_handle;
30
30
  void *funchook_reference, *(*funchook_create)(void);
31
- /* This variables are used to load the funchook dylib */
32
- #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
33
- #pragma GCC diagnostic push
31
+ /* This variables are used to load the funchook dylib */
32
+ #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
33
+ #pragma GCC diagnostic push
34
34
  int prepareResult, (*funchook_prepare)(void *, void **, void *);
35
35
  int installResult, (*funchook_install)(void *, int);
36
- #pragma GCC diagnostic pop
36
+ #pragma GCC diagnostic pop
37
37
 
38
38
  funchook_lib_handle =
39
39
  dlopen(StringValueCStr(funchook_path), RTLD_NOW | RTLD_GLOBAL);
@@ -198,7 +198,7 @@ extern VALUE contrast_lookout_prepended(VALUE self, VALUE object_name,
198
198
  }
199
199
 
200
200
  VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
201
- VALUE is_instance) {
201
+ VALUE is_instance) {
202
202
  VALUE entry, ancestors, entry_methods;
203
203
  VALUE result = Qfalse;
204
204
  VALUE object_idx = Qnil;
@@ -107,7 +107,8 @@ VALUE rescue_func(VALUE arg1) {
107
107
  *
108
108
  **/
109
109
  VALUE contrast_patch_call_ensure(const VALUE *args) {
110
- /* we do not need to ensure that post patch is called if no error was thrown */
110
+ /* we do not need to ensure that post patch is called if no error was thrown
111
+ */
111
112
  if (!RTEST(rb_errinfo())) {
112
113
  return Qnil;
113
114
  }
@@ -3,9 +3,9 @@
3
3
 
4
4
  #include "cs__scope.h"
5
5
  #include "../cs__common/cs__common.h"
6
+ #include <pthread.h>
6
7
  #include <ruby.h>
7
8
  #include <stdlib.h>
8
- #include <pthread.h>
9
9
 
10
10
  /*-----------------------------------------
11
11
  | Calls to Contrast modules and classes
@@ -161,8 +161,8 @@ VALUE contrast_scope_application_update() {
161
161
  return INT2FIX(env_var_set(eVar));
162
162
  }
163
163
 
164
- /**
165
- * @brief Determines if the Contrast Scope should be set with the Trap Context.
164
+ /**
165
+ * @brief Determines if the Contrast Scope should be set with the Trap Context.
166
166
  * @return 1 if set, 0 if not set.
167
167
  */
168
168
  int contrast_scope_with_trap_context() {
@@ -556,7 +556,7 @@ VALUE contrast_scope_for_current_ec(VALUE self, VALUE args) {
556
556
  * different thread, at once, but since the mutex stays in
557
557
  * the C API context, this might work fine. Still use only
558
558
  * when unusual conditions are met.
559
- *
559
+ *
560
560
  * In addition we could use C mutex lock just in case. Ruby
561
561
  * Threads under the hood are C threads (pthread), so they
562
562
  * should be treated as such. In theory only one thread can
@@ -894,7 +894,8 @@ void Init_cs__scope() {
894
894
  rb_const_ec = "EXECUTION_CONTEXT";
895
895
  rb_const_ec_keys = "EC_KEYS";
896
896
  c_const_ctr_agent_app_scope = "CONTRAST__AGENT__RUBY__APPLICATION_SCOPE";
897
- c_const_ctr_agent_scope_trap_context = "CONTRAST__AGENT__SCOPE__WITH_TRAP_CONTEXT";
897
+ c_const_ctr_agent_scope_trap_context =
898
+ "CONTRAST__AGENT__SCOPE__WITH_TRAP_CONTEXT";
898
899
 
899
900
  /* Symbols */
900
901
  rb_sym_scope_mod = rb_intern("Scope");
@@ -5,9 +5,18 @@ module Contrast
5
5
  module Agent
6
6
  module Assess
7
7
  module Events
8
- # this class will gather and build event
8
+ # this class will gather and build event.
9
9
  class EventData
10
- attr_reader :policy_node, :tagged, :object, :ret, :args
10
+ # @return [Contrast::Agent::Assess::Policy::PolicyNode, nil] the node that governs this event.
11
+ attr_reader :policy_node
12
+ # @return [Object, nil] the Target to which this event pertains.
13
+ attr_reader :tagged
14
+ # @return [Object, nil] the Object on which the method was invoked.
15
+ attr_reader :object
16
+ # @return [Object, nil] the Return of the invoked method.
17
+ attr_reader :ret
18
+ # @return [Array<Object>, nil] the Arguments with which the method was invoked.
19
+ attr_reader :args
11
20
 
12
21
  # Group event data together
13
22
  #
@@ -8,6 +8,7 @@ require 'contrast/agent/assess/tracker'
8
8
  class Object
9
9
  alias_method :cs__patched_object_freeze, :freeze
10
10
 
11
+ # Applies the the freeze patch and handles the pre-finalizes the object.
11
12
  def freeze
12
13
  Contrast::Agent::Assess::Tracker.pre_freeze(self)
13
14
  cs__patched_object_freeze
@@ -16,6 +16,10 @@ module Contrast
16
16
  FROZEN_FINALIZED_IDS = Set.new
17
17
  KEEP_AGE = 600_000.cs__freeze # 10 minutes
18
18
 
19
+ # Store the given Object in the Hash, using its __id__ as the key. If the Object is frozen, we need to
20
+ # pre-finalize it and store its __id__ in our tracking Set.
21
+ #
22
+ # @return [Object] the Object stored
19
23
  def []= key, obj
20
24
  return unless obj
21
25
  return unless ::Contrast::AGENT.enabled? && ::Contrast::ASSESS.enabled?
@@ -29,6 +33,9 @@ module Contrast
29
33
  super(key.__id__, obj)
30
34
  end
31
35
 
36
+ # Retrieves the Object stored in the Hash by its __id__.
37
+ #
38
+ # @return [Object, nil] the Object stored.
32
39
  def [] key
33
40
  super(key.__id__)
34
41
  end
@@ -34,6 +34,8 @@ module Contrast
34
34
  # load. These methods only exist once a module or class eval has been
35
35
  # called. This hook is provided so that patches to those methods can
36
36
  # pass us execution flow once a new method has been made available.
37
+ #
38
+ # @param mod [Module]
37
39
  def patch_assess_on_eval mod
38
40
  return unless ::Contrast::ASSESS.enabled?
39
41
  return if in_contrast_scope?
@@ -34,6 +34,8 @@ module Contrast
34
34
 
35
35
  # Indicates is this feature has been disabled by the configuration,
36
36
  # read at startup, and therefore can never be enabled.
37
+ #
38
+ # @return [Boolean] if this feature is disabled
37
39
  def disabled_globally?
38
40
  ::Contrast::ASSESS.forcibly_disabled?
39
41
  end
@@ -49,6 +51,8 @@ module Contrast
49
51
  # This let's us be flexible and extensible
50
52
  # * when we want to do lvl 2 rules, we could have the customers unzip
51
53
  # our gem, insert things into the json, zip, and go *
54
+ #
55
+ # @param string [String]
52
56
  def from_hash_string string
53
57
  # The default behavior of the agent is to load the policy on startup,
54
58
  # as at this point we do not know in which mode we'll be run.
@@ -26,8 +26,17 @@ module Contrast
26
26
  JSON_TARGET = 'target'
27
27
  TO_MARKER = '2'
28
28
 
29
- attr_accessor :tags, :type
30
- attr_reader :sources, :targets, :source_string, :target_string
29
+ # @return [Set<String>]
30
+ attr_accessor :tags
31
+ # @return [Symbol]
32
+ attr_accessor :type
33
+ attr_reader :sources
34
+ # @return [Array<String>]
35
+ attr_reader :targets
36
+ # @return [String]
37
+ attr_reader :source_string
38
+ # @return [String]
39
+ attr_reader :target_string
31
40
 
32
41
  # Here are all methods that can use original objects without mutation the source.
33
42
  # For methods with REMOVE action, their (!) bang alternative is not listed, since
@@ -68,6 +77,8 @@ module Contrast
68
77
  # String#to_s => self or string. This method is included here to cover the situations such as
69
78
  # String.to_s.html_safe, where normally the dynamic sources properties get lost. To solve this
70
79
  # we will simply return the original object here.
80
+ #
81
+ # @param policy_hash [Hash]
71
82
  def assign_on_bang_check policy_hash
72
83
  return true if @_use_original_object && TO_S.include?(policy_hash[JSON_METHOD_NAME])
73
84
 
@@ -76,18 +87,24 @@ module Contrast
76
87
  policy_hash[JSON_METHOD_NAME].end_with?(Contrast::Utils::ObjectShare::BANG)
77
88
  end
78
89
 
90
+ # @return [String]
79
91
  def feature
80
92
  'Assess'
81
93
  end
82
94
 
95
+ # @return [String]
83
96
  def node_class
84
97
  'Node'
85
98
  end
86
99
 
100
+ # @return [Symbol]
87
101
  def node_type
88
102
  :TYPE_METHOD
89
103
  end
90
104
 
105
+ # Set the target string.
106
+ #
107
+ # @param value [String]
91
108
  def target_string= value
92
109
  @target_string = value
93
110
  @targets = convert_policy_markers(value)
@@ -96,6 +113,9 @@ module Contrast
96
113
  # Sometimes we need to tie information to an event. We'll add a
97
114
  # properties section to the patch node, which can pass them along to
98
115
  # the pre-dtm event
116
+ #
117
+ # @param name [String]
118
+ # @param value [String]
99
119
  def add_property name, value
100
120
  return unless name && value
101
121
 
@@ -103,6 +123,8 @@ module Contrast
103
123
  @properties[name] = value
104
124
  end
105
125
 
126
+ # @param name [String]
127
+ # @return [String]
106
128
  def get_property name
107
129
  return unless @properties
108
130
 
@@ -112,6 +134,8 @@ module Contrast
112
134
  # Don't let nodes be created that will be missing things we need
113
135
  # later on. Really, if they don't have these things, they couldn't have
114
136
  # done their jobs anyway.
137
+ #
138
+ # @raise [ArgumentError] raises if the node is invalid.
115
139
  def validate
116
140
  super
117
141
  validate_tags
@@ -124,11 +148,10 @@ module Contrast
124
148
  # isn't a matching ENUM in TS land, the database gets got. We really
125
149
  # don't want to get them, so we're going to prevent the node from being
126
150
  # made.
151
+ #
127
152
  # @raise[ArgumentError] raises if any of the tags is invalid
128
153
  def validate_tags
129
- return unless tags
130
-
131
- tags.each do |tag|
154
+ tags&.each do |tag|
132
155
  next if Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_TAGS.include?(tag) ||
133
156
  Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_SOURCE_TAGS.include?(tag)
134
157
 
@@ -159,8 +182,7 @@ module Contrast
159
182
  # by changing them to 'A'
160
183
  source = all_type?(source_string) ? ALL_TYPE : source_string
161
184
  target = all_type?(target_string) ? ALL_TYPE : target_string
162
- str = source[0] + TO_MARKER + target[0]
163
- str.to_sym
185
+ (source[0] + TO_MARKER + target[0]).to_sym
164
186
  end
165
187
  end
166
188
 
@@ -21,7 +21,15 @@ module Contrast
21
21
  UNDUPLICABLE_MODULES << IO::Buffer if RUBY_VERSION >= '3.1.0'
22
22
  UNDUPLICABLE_MODULES.cs__freeze
23
23
 
24
- attr_accessor :object, :object_length, :args, :arg_lengths
24
+ # @return [Object] the object on which the method is to be called.
25
+ attr_accessor :object
26
+ # @return [Integer] the length of the object on which the method is to
27
+ # be called.
28
+ attr_accessor :object_length
29
+ # @return [Array<Object>] the arguments to be passed to the method.
30
+ attr_accessor :args
31
+ # @return [Array<Integer>] the lengths of the arguments to be passed to
32
+ attr_accessor :arg_lengths
25
33
 
26
34
  class << self
27
35
  # Save the state before we do the propagation. This is one of the
@@ -65,10 +73,23 @@ module Contrast
65
73
 
66
74
  private
67
75
 
76
+ # Determine if the given object is an IO object that is closed, not in
77
+ # initialization, and therefore unsafe to use.
78
+ #
79
+ # @param object [Object] the object on which the method is to be
80
+ # called.
81
+ # @param initializing [Boolean] whether or not the method being
82
+ # called is the initialize method.
68
83
  def unsafe_io_object? object, initializing
69
84
  Contrast::Utils::DuckUtils.closable_io?(object) && !initializing && object.closed?
70
85
  end
71
86
 
87
+ # check if object is duplicable
88
+ #
89
+ # @param initializing [Boolean] whether or not the method being
90
+ # called is the initialize method.
91
+ # @param object [Object] the object on which the method is to be
92
+ # called.
72
93
  def can_dup? initializing, object
73
94
  return false if initializing
74
95
 
@@ -76,6 +97,14 @@ module Contrast
76
97
  !UNDUPLICABLE_MODULES.include?(check)
77
98
  end
78
99
 
100
+ # Appends the object details to the given preshift and adds it to the LRU cache.
101
+ #
102
+ # @param preshift [Contrast::Agent::Assess::PreShift] the preshift to
103
+ # which the object details should be appended.
104
+ # @param initializing [Boolean] whether or not the method being
105
+ # called is the initialize method.
106
+ # @param object [Object] the object on which the method is to be
107
+ # called.
79
108
  def append_object_details preshift, initializing, object
80
109
  can = can_dup?(initializing, object)
81
110
  preshift.object = if @lru_cache.key?(object.__id__) && !Contrast::Agent::Assess::Tracker.tracked?(object)
@@ -97,6 +126,10 @@ module Contrast
97
126
  @lru_cache[object.__id__] = object
98
127
  end
99
128
 
129
+ # @param preshift [Contrast::Agent::Assess::PreShift] the preshift to
130
+ # which the argument details should be appended.
131
+ # @param args [Array<Object>] the arguments to be passed to the
132
+ # method.
100
133
  def append_arg_details preshift, args
101
134
  args_length = args.length
102
135
  preshift.args = Array.new(args_length)
@@ -88,6 +88,7 @@ module Contrast
88
88
  end
89
89
 
90
90
  # If this patcher has tags, apply them to the entire target
91
+ #
91
92
  # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
92
93
  # propagation event.
93
94
  # @param target [Object] the Target to which to propagate.
@@ -101,6 +102,9 @@ module Contrast
101
102
  end
102
103
  end
103
104
 
105
+ # Checks to see if the given target is valid for propagation.
106
+ #
107
+ # @return [Bool]
104
108
  def context_available?
105
109
  !!Contrast::Agent::REQUEST_TRACKER.current
106
110
  end
@@ -121,7 +125,8 @@ module Contrast
121
125
 
122
126
  private
123
127
 
124
- # This is checked right before actual propagation
128
+ # This is checked right before actual propagation.
129
+ #
125
130
  # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
126
131
  # propagation event.
127
132
  # @param target [Object] the Target to which to propagate.
@@ -198,6 +203,10 @@ module Contrast
198
203
  increment_event_count(propagation_node)
199
204
  end
200
205
 
206
+ # @param propagation_class [Contrast::Agent::Assess::Policy::Propagator]
207
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
208
+ # @param source [Object] The object from which the propagation begins.
209
+ # @param target [Object] the Target to which to propagate.
201
210
  def handle_propagation propagation_class, propagation_node, source, target
202
211
  if propagation_node.patch_method
203
212
  propagation_class.send(propagation_node.patch_method, propagation_node, source, target)
@@ -206,6 +215,12 @@ module Contrast
206
215
  end
207
216
  end
208
217
 
218
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
219
+ # @param target [Object] the Target to which to propagate.
220
+ # @param propagation_data [Contrast::Agent::Assess::Events::EventData] this will hold the
221
+ # object [Object] the Object on which the method was invoked
222
+ # ret [Object] the Return of the invoked method
223
+ # args [Array<Object>] the Arguments with which the method was invoked
209
224
  def update_properties propagation_node, target, propagation_data
210
225
  if propagation_node.use_original_on_bang_method?
211
226
  properties = use_original_object_properties(propagation_data)
@@ -22,7 +22,34 @@ module Contrast
22
22
  JSON_PATCH_CLASS = 'patch_class'
23
23
  JSON_PATCH_METHOD = 'patch_method'
24
24
 
25
- attr_reader :action, :untags, :patch_method
25
+ # @return action [String] the action to be taken by this propagation
26
+ # node. This can be one of the following:
27
+ # - 'CUSTOM' - the propagation node is a custom propagation node
28
+ # - 'DB_WRITE' - the propagation node is a database write propagation
29
+ # node
30
+ # - 'APPEND' - the propagation node is an append propagation node
31
+ # - 'CENTER' - the propagation node is a center propagation node
32
+ # - 'INSERT' - the propagation node is an insert propagation node
33
+ # - 'KEEP' - the propagation node is a keep propagation node
34
+ # - 'NEXT' - the propagation node is a next propagation node
35
+ # - 'BUFFER' - the propagation node is a buffer propagation node
36
+ # - 'NOOP' - the propagation node is a noop propagation node
37
+ # - 'PREPEND' - the propagation node is a prepend propagation node
38
+ # - 'REPLACE' - the propagation node is a replace propagation node
39
+ # - 'REMOVE' - the propagation node is a remove propagation node
40
+ # - 'REVERSE' - the propagation node is a reverse propagation node
41
+ # - 'RESPONSE' - the propagation node is a response propagation node
42
+ # - 'SPLAT' - the propagation node is a splat propagation node
43
+ # - 'SPLIT' - the propagation node is a split propagation node
44
+ attr_reader :action
45
+ # @return untags [Array<String>] the tags to be removed from the
46
+ # target of this propagation node.
47
+ attr_reader :untags
48
+ # @return patch_class [String] the class name of the class that
49
+ # contains the method to be called for this propagation node.
50
+ attr_reader :patch_method
51
+ # @return patch_method [Symbol] the name of the method to be called
52
+ # for this propagation node.
26
53
  attr_accessor :patch_class
27
54
 
28
55
  TAGGER = 'Tagger'
@@ -36,6 +63,9 @@ module Contrast
36
63
  # Tags - array of tags to apply to the target, can be nil if no tags are added
37
64
  # Untags - array of tags to remove from the target, can be nil if not tags are removed
38
65
  # id, class_name, instance_method, method_name, source, target, action, tags = nil, untags = nil
66
+ #
67
+ # @param propagation_hash [Hash] the hash from which to build the
68
+ # propagation node.
39
69
  def initialize propagation_hash = {}
40
70
  super(propagation_hash)
41
71
  @action = propagation_hash[JSON_ACTION]
@@ -49,6 +79,7 @@ module Contrast
49
79
  nil
50
80
  end
51
81
 
82
+ # @return [String] class name
52
83
  def node_class
53
84
  @_node_class ||= tagger? ? TAGGER : PROPAGATOR
54
85
  end
@@ -56,12 +87,15 @@ module Contrast
56
87
  # Unlike the other agents, we don't have separate tag & propagation
57
88
  # events. To make TS happy, we need to have different types though.
58
89
  # Pretty straight forward: if there's a tag, this is a tagger
90
+ #
91
+ # @return [Symbol] the type of node.
59
92
  def node_type
60
93
  tagger? ? :TYPE_TAG : :TYPE_PROPAGATION
61
94
  end
62
95
 
63
96
  # Standard validation + TS trace version two rules:
64
97
  # Must have source, target, and action
98
+ #
65
99
  # @raise[ArgumentError] raises if any of the required propagation node field is not valid, or is missing
66
100
  def validate
67
101
  super
@@ -100,6 +134,8 @@ module Contrast
100
134
  end
101
135
  end
102
136
 
137
+ # @return [Boolean]
138
+ # propagation node.
103
139
  def needs_object?
104
140
  if @_needs_object.nil?
105
141
  @_needs_object = action == Contrast::Utils::Assess::PropagationMethodUtils::CUSTOM_ACTION ||
@@ -110,6 +146,7 @@ module Contrast
110
146
  @_needs_object
111
147
  end
112
148
 
149
+ # @return [Boolean]
113
150
  def needs_args?
114
151
  if @_needs_args.nil?
115
152
  @_needs_args = action == Contrast::Utils::Assess::PropagationMethodUtils::CUSTOM_ACTION ||
@@ -124,6 +161,8 @@ module Contrast
124
161
  # It indicates this method is more than just a transformation,
125
162
  # it is an interesting security event that has a meaningful
126
163
  # change.
164
+ #
165
+ # @return [Boolean]
127
166
  def tagger?
128
167
  @_tagger = tags&.any? || untags&.any? if @_tagger.nil?
129
168
  @_tagger
@@ -15,6 +15,11 @@ module Contrast
15
15
  # if the target length is greater than the source
16
16
  # copy tags from the param to the target in chunks of param size or less
17
17
  # if param is appended in space less than param length
18
+ #
19
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
20
+ # propagation action required by this method.
21
+ # @param preshift [Object] pre call state of the things.
22
+ # @param target [Object] the object to which the source is being appended
18
23
  def propagate propagation_node, preshift, target
19
24
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
20
25
 
@@ -12,6 +12,10 @@ module Contrast
12
12
  # to pass tags from it to a Target.
13
13
  class Base
14
14
  class << self
15
+ # Retrieve the source from the preshift state.
16
+ #
17
+ # @param source [Symbol] the source to retrieve.
18
+ # @param preshift [Contrast::Agent::Assess::PreShift] the pre-call state of the things.
15
19
  def find_source source, preshift
16
20
  case source
17
21
  when Contrast::Utils::ObjectShare::OBJECT_KEY
@@ -21,10 +25,16 @@ module Contrast
21
25
  end
22
26
  end
23
27
 
28
+ # Check if tags are present on the given target.
29
+ #
30
+ # @return [Boolean]
24
31
  def tracked_value? value
25
32
  Contrast::Agent::Assess::Tracker.tracked?(value)
26
33
  end
27
34
 
35
+ # Propagate the tags from the source to the target.
36
+ # This method should be extended by the subclasses.
37
+ #
28
38
  # @raise [NoMethodError] This is being raised if any of the implementing subclasses does not have
29
39
  # that method implemented, but is being called on.
30
40
  def propagate _propagation_node, _preshift, _target
@@ -17,6 +17,12 @@ module Contrast
17
17
  # Once the tag is applied, shift it to the location of the insert
18
18
  # Unlike additive propagation, this currently only supports one source
19
19
  # We assume that insert changes the preshift target
20
+ #
21
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
22
+ # propagation action required by this method.
23
+ # @param preshift [Object] pre call state of the things.
24
+ # @param target [Object] the object to which the source is being appended
25
+ # @return [Object] the target with the tags applied
20
26
  def propagate_insert propagation_node, preshift, target
21
27
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
22
28
 
@@ -11,6 +11,11 @@ module Contrast
11
11
  # are unaffected beyond any merging of overlapping tags.
12
12
  class Center < Contrast::Agent::Assess::Policy::Propagator::Base
13
13
  class << self
14
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
15
+ # propagation action required by this method.
16
+ # @param preshift [Object] pre call state of the things.
17
+ # @param target [Object] the object to which the source is being appended
18
+ # @return [Object] the target with the tags applied
14
19
  def propagate propagation_node, preshift, target
15
20
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
16
21
 
@@ -56,6 +61,15 @@ module Contrast
56
61
  iterate_tags(target, propagation_node, source, end_index, target.length)
57
62
  end
58
63
 
64
+ # This method will iterate over the tags of the source and apply
65
+ # them to the target.
66
+ #
67
+ # @param target [Object] the thing to apply tags to.
68
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
69
+ # the node that indicates how this propagation should be handled.
70
+ # @param source [Object] the thing to copy tags from.
71
+ # @param start [Integer] where to start copying tags from.
72
+ # @param stop [Integer] where to stop copying tags from.
59
73
  def iterate_tags target, propagation_node, source, start, stop
60
74
  properties = Contrast::Agent::Assess::Tracker.properties(target)
61
75
  while start < stop
@@ -17,6 +17,12 @@ module Contrast
17
17
  extend Contrast::Utils::Assess::EventLimitUtils
18
18
 
19
19
  class << self
20
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
21
+ # propagation action required by this method.
22
+ # @param preshift [Object] pre call state of the things.
23
+ # @param ret [Object] the return value of the method.
24
+ # @param block [Proc] the block passed to the method.
25
+ # @return [Object] the return value of the method.
20
26
  def propagate propagation_node, preshift, ret, block
21
27
  clazz = propagation_node.patch_class
22
28
  method = propagation_node.patch_method
@@ -16,6 +16,11 @@ module Contrast
16
16
  extend Contrast::Utils::Assess::EventLimitUtils
17
17
 
18
18
  class << self
19
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
20
+ # propagation action required by this method.
21
+ # @param preshift [Object] pre call state of the things.
22
+ # @param target [Object] the object to which the source is being appended
23
+ # @return [Object] the target with the tags applied
19
24
  def propagate propagation_node, preshift, target
20
25
  return unless Contrast::ASSESS.require_dynamic_sources?
21
26
 
@@ -41,6 +46,15 @@ module Contrast
41
46
 
42
47
  private
43
48
 
49
+ # Handles the write propagation for the given source.
50
+ #
51
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
52
+ # propagation action required by this method.
53
+ # @param source [Symbol] the source to retrieve.
54
+ # @param preshift [Contrast::Agent::Assess::PreShift] the pre-call state of the things.
55
+ # @param target [Object] the object to which the source is being appended
56
+ # @param known_tainted [Array] the list of known tainted columns
57
+ # @param tainted_columns [Hash] the hash of tainted columns
44
58
  def handle_write propagation_node, source, preshift, target, known_tainted, tainted_columns
45
59
  arg = preshift.args[source]
46
60
  return unless arg.cs__respond_to?(:each_pair)
@@ -15,6 +15,12 @@ module Contrast
15
15
  # Once the tag is applied, shift it to the location of the insert
16
16
  # Unlike additive propagation, this currently only supports one source
17
17
  # We assume that insert changes the preshift target
18
+ #
19
+ # @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
20
+ # propagation action required by this method.
21
+ # @param preshift [Object] pre call state of the things.
22
+ # @param target [Object] the object to which the source is being appended
23
+ # @return [Object] the target with the tags applied
18
24
  def propagate propagation_node, preshift, target
19
25
  return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
20
26