contrast-agent 3.15.0 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent.rb +2 -9
  3. data/lib/contrast/agent/assess/contrast_event.rb +142 -70
  4. data/lib/contrast/agent/assess/events/source_event.rb +1 -1
  5. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +10 -3
  6. data/lib/contrast/agent/assess/policy/policy_node.rb +15 -10
  7. data/lib/contrast/agent/assess/policy/policy_scanner.rb +7 -1
  8. data/lib/contrast/agent/assess/policy/propagator/insert.rb +1 -1
  9. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +0 -3
  10. data/lib/contrast/agent/assess/policy/propagator/select.rb +1 -3
  11. data/lib/contrast/agent/assess/policy/propagator/splat.rb +0 -5
  12. data/lib/contrast/agent/assess/policy/propagator/split.rb +12 -13
  13. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +21 -14
  14. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +4 -5
  15. data/lib/contrast/agent/assess/policy/trigger_method.rb +39 -14
  16. data/lib/contrast/agent/assess/policy/trigger_node.rb +31 -37
  17. data/lib/contrast/agent/assess/property/evented.rb +5 -18
  18. data/lib/contrast/agent/assess/property/tagged.rb +9 -3
  19. data/lib/contrast/agent/assess/property/updated.rb +0 -5
  20. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +58 -5
  21. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +23 -8
  22. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +82 -14
  23. data/lib/contrast/agent/assess/tag.rb +1 -1
  24. data/lib/contrast/agent/at_exit_hook.rb +5 -5
  25. data/lib/contrast/agent/patching/policy/after_load_patch.rb +5 -5
  26. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +20 -20
  27. data/lib/contrast/agent/patching/policy/module_policy.rb +10 -10
  28. data/lib/contrast/agent/patching/policy/policy.rb +16 -2
  29. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +3 -5
  30. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
  31. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -0
  32. data/lib/contrast/agent/request.rb +34 -34
  33. data/lib/contrast/agent/static_analysis.rb +6 -6
  34. data/lib/contrast/agent/version.rb +1 -1
  35. data/lib/contrast/api/communication/socket_client.rb +36 -1
  36. data/lib/contrast/api/decorators/address.rb +13 -13
  37. data/lib/contrast/api/decorators/message.rb +1 -0
  38. data/lib/contrast/api/decorators/trace_event.rb +20 -18
  39. data/lib/contrast/components/app_context.rb +39 -30
  40. data/lib/contrast/components/contrast_service.rb +9 -9
  41. data/lib/contrast/components/settings.rb +20 -23
  42. data/lib/contrast/config/service_configuration.rb +4 -2
  43. data/lib/contrast/configuration.rb +1 -1
  44. data/lib/contrast/extension/assess/array.rb +7 -3
  45. data/lib/contrast/extension/assess/erb.rb +5 -0
  46. data/lib/contrast/extension/assess/eval_trigger.rb +6 -6
  47. data/lib/contrast/extension/assess/exec_trigger.rb +1 -1
  48. data/lib/contrast/extension/assess/fiber.rb +3 -3
  49. data/lib/contrast/extension/assess/hash.rb +3 -3
  50. data/lib/contrast/extension/assess/kernel.rb +18 -20
  51. data/lib/contrast/extension/assess/marshal.rb +8 -4
  52. data/lib/contrast/extension/assess/regexp.rb +3 -3
  53. data/lib/contrast/extension/assess/string.rb +13 -11
  54. data/lib/contrast/extension/protect/kernel.rb +3 -3
  55. data/lib/contrast/framework/base_support.rb +1 -1
  56. data/lib/contrast/framework/manager.rb +3 -3
  57. data/lib/contrast/framework/rack/patch/session_cookie.rb +9 -9
  58. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +13 -13
  59. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +10 -10
  60. data/lib/contrast/framework/rails/patch/support.rb +1 -1
  61. data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +11 -11
  62. data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +12 -12
  63. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +3 -3
  64. data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +12 -12
  65. data/lib/contrast/framework/sinatra/patch/base.rb +11 -11
  66. data/lib/contrast/framework/sinatra/support.rb +4 -4
  67. data/lib/contrast/logger/log.rb +7 -2
  68. data/lib/contrast/utils/invalid_configuration_util.rb +2 -5
  69. data/resources/assess/policy.json +31 -12
  70. data/ruby-agent.gemspec +4 -3
  71. data/service_executables/VERSION +1 -1
  72. data/service_executables/linux/contrast-service +0 -0
  73. data/service_executables/mac/contrast-service +0 -0
  74. metadata +31 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac8fc7d0e9c127859cf7bdb149c7ac519286c4329bd81ad28db4963128e0cd63
4
- data.tar.gz: 784afc67ef269df8dfbaed392e8ad28e2e3b679113ed8679625f95033e324929
3
+ metadata.gz: c2172066d6736b55c6754bb6913ec9fb9962ac1b818a85b4faa7ef822bb5df97
4
+ data.tar.gz: 209286f4ef6ce8b688e3849a502ece6cfc914f795fae25b5cb417b3fa3998b50
5
5
  SHA512:
6
- metadata.gz: c1a5563b34a4eba33fdf8094986362f70c88bda53102899bb01ad0096588d26883b5e7ad475e41afa15b95674b8c2810cfe6546c6779b8e3b2030bf7bb1e33d6
7
- data.tar.gz: 1a1eb220719c1caf3f7153108bff4ac5132130d6879dc2b425e6dd31720e4c76bda9c27c0ac65fa00ccb846a31cb173e04dc7d3320ba3079ea9b785a62991f00
6
+ metadata.gz: e6c19a309c1d7c7e2600d2f90d5da2664c315550be00475720165dde741d821d3ceb391282831aeb8ddcbe8e86b50b48d741d5c63d85c7a92c38ef0e54b7b0cd
7
+ data.tar.gz: f4c1a92e5272730285b467c63768e31b1d6d7cb4266cbd6133c6de312603fcabc9c3bc814bc7f20d48fa444651fb040713ed1438b70076e9be9be396dab6603b
@@ -94,12 +94,5 @@ require 'contrast/utils/gemfile_reader'
94
94
  # rack event monitoring
95
95
  require 'contrast/agent/middleware'
96
96
 
97
- # TODO: RUBY-919
98
- # Refactor to use Contrast::Framework::Manager
99
- # Contrast::Framework::Manager.before_load_patches!
100
- if defined?(::Rails)
101
- require 'contrast/framework/rails/patch/support'
102
- require 'contrast/framework/rails/patch/rails_application_configuration'
103
- Contrast::Framework::Rails::Patch::RailsApplicationConfiguration.instrument
104
- require 'contrast/agent/railtie' if ::Rails::VERSION::MAJOR.to_i >= 3
105
- end
97
+ # Install the patches we need before the application has a chance to initialize
98
+ Contrast::Agent.framework_manager.before_load_patches!
@@ -16,10 +16,32 @@ module Contrast
16
16
  # This class holds the data about an event in the application
17
17
  # We'll use it to build an event that TeamServer can consume if
18
18
  # the object to which this event belongs ends in a trigger.
19
+ #
20
+ # @attr_reader event_id [Integer] the atomic id of this event
21
+ # @attr_reader policy_node [Contrast::Agent::Assess::Policy::PolicyNode]
22
+ # the node that governs this event.
23
+ # @attr_reader stack_trace [Array<String>] the execution stack at the
24
+ # time the method for this event was invoked
25
+ # @attr_reader time [Integer] the time, in epoch ms, when this event was
26
+ # created
27
+ # @attr_reader thread [Integer] the object id of the thread on which this
28
+ # event was generated
29
+ # @attr_reader object [String] the safe representation of the Object on
30
+ # which the method was invoked
31
+ # @attr_reader ret [String] the safe representation of the Return of the
32
+ # invoked method
33
+ # @attr_reader args [Array<Object>] the safe representation of the
34
+ # Arguments with which the method was invoked
19
35
  class ContrastEvent
20
36
  include Contrast::Utils::PreventSerialization
21
37
 
22
38
  class << self
39
+ # Given an array of arguments, copy them into a safe, meaning String,
40
+ # format that we can use to send to SR and TS for rendering.
41
+ #
42
+ # @param args [Array<Object>] the arguments to translate
43
+ # @return [Array<String>] the String forms of those Objects, as
44
+ # determined by Contrast::Utils::ClassUtil.to_contrast_string
23
45
  def safe_args_representation args
24
46
  return nil unless args
25
47
  return Contrast::Utils::ObjectShare::EMPTY_ARRAY if args.empty?
@@ -36,26 +58,31 @@ module Contrast
36
58
  rep
37
59
  end
38
60
 
39
- def safe_arg_hash_representation hash
40
- # since this is the named hash for arguments, only the value is
41
- # suspect here
42
- hash.transform_values { |v| Contrast::Utils::ClassUtil.to_contrast_string(v) }
43
- end
44
-
45
61
  # if given an object that can be duped, duplicate it. otherwise just
46
62
  # return the original object. swallow all exceptions from
47
63
  # non-duplicable things.
48
64
  #
49
65
  # we can't just check respond_to? though b/c dup exists on the
50
66
  # base Object class
67
+ #
68
+ # @param original [Object, nil] the thing to duplicate
69
+ # @return [Object, nil] a copy of that thing
51
70
  def safe_dup original
52
71
  return nil unless original
53
72
 
54
73
  Contrast::Agent::Assess::Tracker.duplicate(original)
55
74
  end
75
+
76
+ private
77
+
78
+ def safe_arg_hash_representation hash
79
+ # since this is the named hash for arguments, only the value is
80
+ # suspect here
81
+ hash.transform_values { |v| Contrast::Utils::ClassUtil.to_contrast_string(v) }
82
+ end
56
83
  end
57
84
 
58
- attr_reader :event_id, :parent_ids, :policy_node, :stack_trace, :time, :thread, :object, :ret, :args
85
+ attr_reader :event_id, :policy_node, :stack_trace, :time, :thread, :object, :ret, :args
59
86
 
60
87
  # We need this to track the parent id's of events to build up a flow
61
88
  # chart of the finding
@@ -70,6 +97,13 @@ module Contrast
70
97
  end
71
98
  end
72
99
 
100
+ # @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode]
101
+ # the node that governs this event.
102
+ # @param tagged [Object] the Target to which this event pertains.
103
+ # @param object [Object] the Object on which the method was invoked
104
+ # @param ret [Object] the Return of the invoked method
105
+ # @param args [Array<Object>] the Arguments with which the method
106
+ # was invoked
73
107
  def initialize policy_node, tagged, object, ret, args
74
108
  @policy_node = policy_node
75
109
  # so long as this event is built in a factory, we know Contrast Code
@@ -80,26 +114,110 @@ module Contrast
80
114
 
81
115
  # These methods rely on the above being set. Don't move them!
82
116
  @event_id = Contrast::Agent::Assess::ContrastEvent.next_atomic_id
83
- @parent_ids = find_parent_ids(policy_node, object, ret, args)
84
- snapshot(tagged, object, ret, args)
117
+ find_parent_events!(policy_node, object, ret, args)
118
+ snapshot!(tagged, object, ret, args)
85
119
  end
86
120
 
87
- # Parent IDs are the event ids of all the sources of this event which
88
- # were tracked prior to this event occurring
89
- def find_parent_ids policy_node, object, ret, args
90
- mapped = policy_node.sources.map do |source|
91
- value_of_source(source, object, ret, args)
121
+ def parent_events
122
+ @_parent_events ||= []
123
+ end
124
+
125
+ # We have to do a little work to figure out what our TS appropriate
126
+ # target is. To break this down, the logic is as follows:
127
+ # 1) If my policy_node has a target, work on targets. Else, work on sources.
128
+ # Per TS law, each policy_node must have at least a source or a target.
129
+ # The only type of policy_node w/o targets is a Trigger, but that may
130
+ # change.
131
+ # 2) If I have a highlight, it means that I have a P target that is
132
+ # not in integer form (it was a named / keyword type for which I had
133
+ # to find the index). I need to address this so that TS can process
134
+ # it.
135
+ # 3) I'll set the event's source and target to TS values.
136
+ # 4) Return the highlight or the first source/target as the taint
137
+ # target.
138
+ def determine_taint_target event_dtm
139
+ if @policy_node&.targets&.any?
140
+ event_dtm.source = @policy_node.source_string if @policy_node.source_string
141
+ event_dtm.target = @highlight ? "P#{ @highlight }" : @policy_node.target_string
142
+ @highlight || @policy_node.targets[0]
143
+ elsif policy_node&.sources&.any?
144
+ event_dtm.source = @highlight ? "P#{ @highlight }" : @policy_node.source_string
145
+ event_dtm.target = @policy_node.target_string if @policy_node.target_string
146
+ @highlight || @policy_node.sources[0]
92
147
  end
93
- selected = mapped.select do |source|
94
- source && Contrast::Agent::Assess::Tracker.properties(source)&.events&.last
148
+ end
149
+
150
+ # Convert this event into a DTM that TeamServer can consume
151
+ def to_dtm_event
152
+ Contrast::Api::Dtm::TraceEvent.build(self)
153
+ end
154
+
155
+ private
156
+
157
+ # Parent events are the events of all the sources of this event which
158
+ # were tracked prior to this event occurring. Depending on which, if
159
+ # any of the sources were tracked, there may be more than one parent.
160
+ #
161
+ # All events except for [Contrast::Agent::Assess::Events::SourceEvent]
162
+ # will have at least one parent.
163
+ #
164
+ # We set those events to this event's instance variables.
165
+ #
166
+ # @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode]
167
+ # the node that governs this event.
168
+ # @param object [Object] the Object on which the method was invoked
169
+ # @param ret [Object] the Return of the invoked method
170
+ # @param args [Array<Object>] the Arguments with which the method
171
+ # was invoked
172
+ def find_parent_events! policy_node, object, ret, args
173
+ policy_node.sources.each do |source_marker|
174
+ source = value_of_source(source_marker, object, ret, args)
175
+ next unless source
176
+
177
+ event = Contrast::Agent::Assess::Tracker.properties(source)&.event
178
+ parent_events << event if event
95
179
  end
96
- selected.map do |source|
97
- properties = Contrast::Agent::Assess::Tracker.properties(source)
98
- properties.events.last.event_id
180
+ end
181
+
182
+ # @param source [String] the marker for the source type
183
+ # @param object [Object] the Object on which the method was invoked
184
+ # @param ret [Object] the Return of the invoked method
185
+ # @param args [Array<Object>] the Arguments with which the method
186
+ # was invoked
187
+ # @return [Object,nil] the literal value of the source indicated by the
188
+ # given marker
189
+ def value_of_source source, object, ret, args
190
+ case source
191
+ when Contrast::Utils::ObjectShare::OBJECT_KEY
192
+ object
193
+ when Contrast::Utils::ObjectShare::RETURN_KEY
194
+ ret
195
+ else
196
+ if source.is_a?(Integer)
197
+ args[source]
198
+ else
199
+ args.each do |search|
200
+ next unless search.is_a?(Hash)
201
+
202
+ s = search[source]
203
+ return s if s
204
+ end
205
+ end
99
206
  end
100
207
  end
101
208
 
102
- def snapshot tagged, object, ret, args
209
+ # Everything* is mutable in Ruby. As such, to ensure we can accurately
210
+ # report the application state at the time of this method's invocation,
211
+ # we have to snapshot the given values, making safe representations of
212
+ # them for our later use. We set those safe values to this event's
213
+ # instance variables.
214
+ #
215
+ # @param tagged [Object] the Target to which this event pertains.
216
+ # @param object [Object] the Object on which the method was invoked
217
+ # @param ret [Object] the Return of the invoked method
218
+ # @param args [Array<Object>] the Arguments with which the method
219
+ # was invoked
220
+ def snapshot! tagged, object, ret, args
103
221
  target = @policy_node.target
104
222
  case target
105
223
  # If the target is nil, this rule was violated simply by a method
@@ -133,6 +251,10 @@ module Contrast
133
251
  # I know we're creating an extra string here since we replace the safe
134
252
  # one w/ a dup, but good enough for now. Trying not to make this too
135
253
  # complicated. - HM 8/8/19
254
+ #
255
+ # @param target [String,Integer] the marker for the target index
256
+ # @param tagged [Object] the actual Object that we're acting on which
257
+ # has tags
136
258
  def save_target_arg target, tagged
137
259
  return if @args.cs__frozen?
138
260
 
@@ -150,56 +272,6 @@ module Contrast
150
272
  break
151
273
  end
152
274
  end
153
-
154
- # We have to do a little work to figure out what our TS appropriate
155
- # target is. To break this down, the logic is as follows:
156
- # 1) If my policy_node has a target, work on targets. Else, work on sources.
157
- # Per TS law, each policy_node must have at least a source or a target.
158
- # The only type of policy_node w/o targets is a Trigger, but that may
159
- # change.
160
- # 2) If I have a highlight, it means that I have a P target that is
161
- # not in integer form (it was a named / keyword type for which I had
162
- # to find the index). I need to address this so that TS can process
163
- # it.
164
- # 3) I'll set the event's source and target to TS values.
165
- # 4) Return the highlight or the first source/target as the taint
166
- # target.
167
- def determine_taint_target event_dtm
168
- if @policy_node&.targets&.any?
169
- event_dtm.source = @policy_node.source_string if @policy_node.source_string
170
- event_dtm.target = @highlight ? "P#{ @highlight }" : @policy_node.target_string
171
- @highlight || @policy_node.targets[0]
172
- elsif policy_node&.sources&.any?
173
- event_dtm.source = @highlight ? "P#{ @highlight }" : @policy_node.source_string
174
- event_dtm.target = @policy_node.target_string if @policy_node.target_string
175
- @highlight || @policy_node.sources[0]
176
- end
177
- end
178
-
179
- def value_of_source source, object, ret, args
180
- case source
181
- when Contrast::Utils::ObjectShare::OBJECT_KEY
182
- object
183
- when Contrast::Utils::ObjectShare::RETURN_KEY
184
- ret
185
- else
186
- if source.is_a?(Integer)
187
- args[source]
188
- else
189
- args.each do |search|
190
- next unless search.is_a?(Hash)
191
-
192
- s = search[source]
193
- return s if s
194
- end
195
- end
196
- end
197
- end
198
-
199
- # Convert this event into a DTM that TeamServer can consume
200
- def to_dtm_event
201
- Contrast::Api::Dtm::TraceEvent.build(self)
202
- end
203
275
  end
204
276
  end
205
277
  end
@@ -21,7 +21,7 @@ module Contrast
21
21
  @request = Contrast::Agent::REQUEST_TRACKER.current&.request
22
22
  end
23
23
 
24
- def find_parent_ids _policy_node, _object, _ret, _args
24
+ def parent_events
25
25
  nil
26
26
  end
27
27
 
@@ -110,16 +110,23 @@ module Contrast
110
110
  dynamic_source.method_name = Contrast::Utils::StringUtils.force_utf8(field)
111
111
  dynamic_source.instance_method = source_node.instance_method?
112
112
  dynamic_source.target = Contrast::Utils::StringUtils.force_utf8(source_node.target_string)
113
- properties.events.each do |event|
114
- dynamic_source.events << event.to_dtm_event
115
- end
116
113
  dynamic_source.properties[READ_TABLE] = Contrast::Utils::StringUtils.force_utf8(source_node.class_name)
117
114
  dynamic_source.properties[READ_COLUMN] = Contrast::Utils::StringUtils.force_utf8(field)
118
115
  dynamic_source.properties[WRITE_QUERY_TIME] = Contrast::Utils::StringUtils.force_utf8(Contrast::Utils::Timer.now_ms)
119
116
  url = current_context.request.normalized_uri
120
117
  dynamic_source.properties[WRITE_QUERY_URL] = Contrast::Utils::StringUtils.force_utf8(url)
118
+ append_events(dynamic_source, properties.event)
121
119
  dynamic_source
122
120
  end
121
+
122
+ def append_events dynamic_source, event
123
+ return unless event
124
+
125
+ event.parent_events&.each do |parent_event|
126
+ append_events(dynamic_source, parent_event)
127
+ end
128
+ dynamic_source.events << event.to_dtm_event
129
+ end
123
130
  end
124
131
  end
125
132
  end
@@ -157,19 +157,24 @@ module Contrast
157
157
  # Everything else (propagation nodes) are Source2Target
158
158
  def build_action
159
159
  @event_action ||= begin
160
- source = source_string
161
- target = target_string
162
- if source.nil?
160
+ case node_class
161
+ when Contrast::Agent::Assess::Policy::SourceNode::SOURCE
163
162
  :CREATION
164
- elsif target.nil?
163
+ when Contrast::Agent::Assess::Policy::TriggerNode::TRIGGER
165
164
  :TRIGGER
166
165
  else
167
- # TeamServer can't handle the multi-source or multi-target
168
- # values. Give it some help by changing them to 'A'
169
- source = ALL_TYPE if source.include?(Contrast::Utils::ObjectShare::COMMA)
170
- target = ALL_TYPE if target.include?(Contrast::Utils::ObjectShare::COMMA)
171
- str = source[0] + TO_MARKER + target[0]
172
- str.to_sym
166
+ if source_string.nil?
167
+ :CREATION
168
+ elsif target_string.nil?
169
+ :TRIGGER
170
+ else
171
+ # TeamServer can't handle the multi-source or multi-target
172
+ # values. Give it some help by changing them to 'A'
173
+ source = source_string.include?(Contrast::Utils::ObjectShare::COMMA) ? ALL_TYPE : source_string
174
+ target = target_string.include?(Contrast::Utils::ObjectShare::COMMA) ? ALL_TYPE : target_string
175
+ str = source[0] + TO_MARKER + target[0]
176
+ str.to_sym
177
+ end
173
178
  end
174
179
  end
175
180
  @event_action
@@ -27,8 +27,14 @@ module Contrast
27
27
  mod = trace_point.self
28
28
  return if mod.cs__frozen? || mod.singleton_class?
29
29
 
30
+ # TODO: RUBY-1013 - get AST here instead of TP, so we only need
31
+ # to make one per provider, instead of one per rule
30
32
  policy.providers.each_value do |provider|
31
- provider.analyze mod
33
+ if RUBY_VERSION >= '2.6.0'
34
+ provider.parse(trace_point)
35
+ else # TODO: RUBY-1014 - remove alternative
36
+ provider.analyze(mod)
37
+ end
32
38
  end
33
39
  end
34
40
 
@@ -19,7 +19,7 @@ module Contrast
19
19
  properties = Contrast::Agent::Assess::Tracker.properties(target)
20
20
  return unless properties
21
21
 
22
- source = find_source(propagation_node.sources[0], preshift)
22
+ source = find_source(propagation_node.sources[1], preshift)
23
23
 
24
24
  patcher_target = propagation_node.targets[0]
25
25
  preshift_target = case patcher_target
@@ -75,9 +75,6 @@ module Contrast
75
75
  applicable_tags.each do |tag_name, tag_ranges|
76
76
  return_properties.set_tags(tag_name, tag_ranges)
77
77
  end
78
- original_properties.events.each do |event|
79
- return_properties.add_event(event)
80
- end
81
78
  return_properties.build_event(propagation_node, return_value, preshift.object, return_value, preshift.args)
82
79
  end
83
80
  end
@@ -27,13 +27,11 @@ module Contrast
27
27
  unless ret &&
28
28
  !ret.empty? &&
29
29
  Contrast::Agent::Assess::Tracker.tracked?(source)
30
+
30
31
  return
31
32
  end
32
33
 
33
34
  source_properties = Contrast::Agent::Assess::Tracker.properties(source)
34
- source_properties.events.each do |event|
35
- properties.events << event
36
- end
37
35
  properties.build_event(
38
36
  patcher,
39
37
  ret,
@@ -50,11 +50,6 @@ module Contrast
50
50
  next unless input_properties
51
51
 
52
52
  properties.splat_from(input, target)
53
- next if input == target
54
-
55
- input_properties.events.each do |event|
56
- properties.events << event
57
- end
58
53
  end
59
54
  end
60
55
  end
@@ -36,6 +36,8 @@ module Contrast
36
36
  target_id: target.__id__)
37
37
  unless target.is_a?(Array)
38
38
  Contrast::Agent::Assess::Policy::Propagator::Keep.propagate(propagation_node, preshift, target)
39
+ properties = Contrast::Agent::Assess::Tracker.properties(target)
40
+ properties.build_event(propagation_node, target, object, ret, args)
39
41
  return
40
42
  end
41
43
 
@@ -62,9 +64,6 @@ module Contrast
62
64
  tags.each_pair do |key, value|
63
65
  elem_properties.set_tags(key, value)
64
66
  end
65
- source_properties.events.each do |event|
66
- elem_properties.add_event(event)
67
- end
68
67
  elem_properties.build_event(propagation_node, elem, preshift.object, target, preshift.args, 0)
69
68
  elem_properties.add_properties(propagation_node.properties)
70
69
  current_index = current_index + elem_length + separator_length
@@ -145,12 +144,12 @@ module Contrast
145
144
  def instrument_string_split
146
145
  if @_instrument_string_split.nil?
147
146
  @_instrument_string_split = begin
148
- require 'cs__assess_yield_track/cs__assess_yield_track' if AGENT.patch_yield? && Funchook.available?
149
- true
150
- rescue StandardError => e
151
- logger.error('Error loading split rb_yield patch', e)
152
- false
153
- end
147
+ require 'cs__assess_yield_track/cs__assess_yield_track' if AGENT.patch_yield? && Funchook.available?
148
+ true
149
+ rescue StandardError => e
150
+ logger.error('Error loading split rb_yield patch', e)
151
+ false
152
+ end
154
153
  end
155
154
  @_instrument_string_split
156
155
  end
@@ -197,10 +196,10 @@ module Contrast
197
196
  # String#split node
198
197
  def split_node
199
198
  @_split_node ||= begin
200
- Contrast::Agent::Assess::Policy::Policy.instance.propagators.find do |node|
201
- node.class_name == 'String' && node.method_name == :split && node.instance_method?
202
- end
203
- end
199
+ Contrast::Agent::Assess::Policy::Policy.instance.propagators.find do |node|
200
+ node.class_name == 'String' && node.method_name == :split && node.instance_method?
201
+ end
202
+ end
204
203
  end
205
204
  end
206
205
  end