contrast-agent 3.15.0 → 3.16.0

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