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.
- checksums.yaml +4 -4
- data/lib/contrast/agent.rb +2 -9
- data/lib/contrast/agent/assess/contrast_event.rb +142 -70
- data/lib/contrast/agent/assess/events/source_event.rb +1 -1
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +10 -3
- data/lib/contrast/agent/assess/policy/policy_node.rb +15 -10
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +7 -1
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +0 -3
- data/lib/contrast/agent/assess/policy/propagator/select.rb +1 -3
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +0 -5
- data/lib/contrast/agent/assess/policy/propagator/split.rb +12 -13
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +21 -14
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +4 -5
- data/lib/contrast/agent/assess/policy/trigger_method.rb +39 -14
- data/lib/contrast/agent/assess/policy/trigger_node.rb +31 -37
- data/lib/contrast/agent/assess/property/evented.rb +5 -18
- data/lib/contrast/agent/assess/property/tagged.rb +9 -3
- data/lib/contrast/agent/assess/property/updated.rb +0 -5
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +58 -5
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +23 -8
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +82 -14
- data/lib/contrast/agent/assess/tag.rb +1 -1
- data/lib/contrast/agent/at_exit_hook.rb +5 -5
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +5 -5
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +20 -20
- data/lib/contrast/agent/patching/policy/module_policy.rb +10 -10
- data/lib/contrast/agent/patching/policy/policy.rb +16 -2
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +3 -5
- data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -0
- data/lib/contrast/agent/request.rb +34 -34
- data/lib/contrast/agent/static_analysis.rb +6 -6
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/communication/socket_client.rb +36 -1
- data/lib/contrast/api/decorators/address.rb +13 -13
- data/lib/contrast/api/decorators/message.rb +1 -0
- data/lib/contrast/api/decorators/trace_event.rb +20 -18
- data/lib/contrast/components/app_context.rb +39 -30
- data/lib/contrast/components/contrast_service.rb +9 -9
- data/lib/contrast/components/settings.rb +20 -23
- data/lib/contrast/config/service_configuration.rb +4 -2
- data/lib/contrast/configuration.rb +1 -1
- data/lib/contrast/extension/assess/array.rb +7 -3
- data/lib/contrast/extension/assess/erb.rb +5 -0
- data/lib/contrast/extension/assess/eval_trigger.rb +6 -6
- data/lib/contrast/extension/assess/exec_trigger.rb +1 -1
- data/lib/contrast/extension/assess/fiber.rb +3 -3
- data/lib/contrast/extension/assess/hash.rb +3 -3
- data/lib/contrast/extension/assess/kernel.rb +18 -20
- data/lib/contrast/extension/assess/marshal.rb +8 -4
- data/lib/contrast/extension/assess/regexp.rb +3 -3
- data/lib/contrast/extension/assess/string.rb +13 -11
- data/lib/contrast/extension/protect/kernel.rb +3 -3
- data/lib/contrast/framework/base_support.rb +1 -1
- data/lib/contrast/framework/manager.rb +3 -3
- data/lib/contrast/framework/rack/patch/session_cookie.rb +9 -9
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +13 -13
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +10 -10
- data/lib/contrast/framework/rails/patch/support.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +11 -11
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +12 -12
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +3 -3
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +12 -12
- data/lib/contrast/framework/sinatra/patch/base.rb +11 -11
- data/lib/contrast/framework/sinatra/support.rb +4 -4
- data/lib/contrast/logger/log.rb +7 -2
- data/lib/contrast/utils/invalid_configuration_util.rb +2 -5
- data/resources/assess/policy.json +31 -12
- data/ruby-agent.gemspec +4 -3
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +31 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2172066d6736b55c6754bb6913ec9fb9962ac1b818a85b4faa7ef822bb5df97
|
4
|
+
data.tar.gz: 209286f4ef6ce8b688e3849a502ece6cfc914f795fae25b5cb417b3fa3998b50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6c19a309c1d7c7e2600d2f90d5da2664c315550be00475720165dde741d821d3ceb391282831aeb8ddcbe8e86b50b48d741d5c63d85c7a92c38ef0e54b7b0cd
|
7
|
+
data.tar.gz: f4c1a92e5272730285b467c63768e31b1d6d7cb4266cbd6133c6de312603fcabc9c3bc814bc7f20d48fa444651fb040713ed1438b70076e9be9be396dab6603b
|
data/lib/contrast/agent.rb
CHANGED
@@ -94,12 +94,5 @@ require 'contrast/utils/gemfile_reader'
|
|
94
94
|
# rack event monitoring
|
95
95
|
require 'contrast/agent/middleware'
|
96
96
|
|
97
|
-
#
|
98
|
-
|
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, :
|
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
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
94
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
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
|
@@ -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
|
-
|
161
|
-
|
162
|
-
if source.nil?
|
160
|
+
case node_class
|
161
|
+
when Contrast::Agent::Assess::Policy::SourceNode::SOURCE
|
163
162
|
:CREATION
|
164
|
-
|
163
|
+
when Contrast::Agent::Assess::Policy::TriggerNode::TRIGGER
|
165
164
|
:TRIGGER
|
166
165
|
else
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
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
|
-
|
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[
|
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,
|
@@ -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
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
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
|