contrast-agent 4.0.0 → 4.3.2
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/Rakefile +1 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +22 -10
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +4 -3
- data/lib/contrast/agent/assess/contrast_event.rb +49 -130
- data/lib/contrast/agent/assess/contrast_object.rb +51 -0
- data/lib/contrast/agent/assess/events/source_event.rb +4 -9
- data/lib/contrast/agent/assess/policy/patcher.rb +4 -3
- data/lib/contrast/agent/assess/policy/policy_node.rb +31 -59
- data/lib/contrast/agent/assess/policy/preshift.rb +3 -3
- data/lib/contrast/agent/assess/policy/propagation_method.rb +13 -19
- data/lib/contrast/agent/assess/policy/propagation_node.rb +12 -24
- data/lib/contrast/agent/assess/policy/propagator/append.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/center.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -3
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +2 -4
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/select.rb +3 -4
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -4
- data/lib/contrast/agent/assess/policy/propagator/split.rb +73 -117
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +11 -11
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +3 -7
- data/lib/contrast/agent/assess/policy/source_method.rb +2 -14
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +5 -8
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
- data/lib/contrast/agent/assess/property/tagged.rb +21 -15
- data/lib/contrast/agent/assess/rule/redos.rb +1 -1
- data/lib/contrast/agent/assess/tracker.rb +16 -18
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +7 -0
- data/lib/contrast/agent/middleware.rb +50 -1
- data/lib/contrast/agent/patching/policy/method_policy.rb +1 -1
- data/lib/contrast/agent/patching/policy/patch.rb +6 -0
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +47 -1
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +53 -0
- data/lib/contrast/agent/protect/rule/base.rb +63 -14
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +12 -28
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -4
- data/lib/contrast/agent/protect/rule/deserialization.rb +4 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +3 -3
- data/lib/contrast/agent/protect/rule/sqli.rb +3 -3
- data/lib/contrast/agent/protect/rule/xxe.rb +32 -11
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +10 -6
- data/lib/contrast/agent/reaction_processor.rb +1 -1
- data/lib/contrast/agent/response.rb +5 -5
- data/lib/contrast/agent/rewriter.rb +3 -3
- data/lib/contrast/agent/scope.rb +81 -55
- data/lib/contrast/agent/static_analysis.rb +13 -7
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/decorators/library.rb +1 -0
- data/lib/contrast/api/decorators/library_usage_update.rb +1 -0
- data/lib/contrast/api/decorators/trace_event.rb +19 -31
- data/lib/contrast/api/decorators/trace_event_object.rb +11 -3
- data/lib/contrast/api/decorators/trace_event_signature.rb +27 -5
- data/lib/contrast/api/decorators/user_input.rb +2 -1
- data/lib/contrast/common_agent_configuration.rb +2 -1
- data/lib/contrast/components/assess.rb +36 -0
- data/lib/contrast/components/interface.rb +5 -3
- data/lib/contrast/components/scope.rb +72 -6
- data/lib/contrast/components/settings.rb +6 -3
- data/lib/contrast/config/assess_configuration.rb +2 -1
- data/lib/contrast/extension/assess/array.rb +2 -3
- data/lib/contrast/extension/assess/erb.rb +1 -3
- data/lib/contrast/extension/assess/exec_trigger.rb +1 -4
- data/lib/contrast/extension/assess/fiber.rb +2 -3
- data/lib/contrast/extension/assess/hash.rb +4 -2
- data/lib/contrast/extension/assess/kernel.rb +1 -2
- data/lib/contrast/extension/assess/marshal.rb +34 -26
- data/lib/contrast/extension/assess/regexp.rb +3 -8
- data/lib/contrast/extension/assess/string.rb +1 -2
- data/lib/contrast/framework/base_support.rb +51 -53
- data/lib/contrast/framework/manager.rb +3 -2
- data/lib/contrast/framework/rack/patch/session_cookie.rb +2 -2
- data/lib/contrast/framework/rack/support.rb +2 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -1
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +1 -1
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +1 -1
- data/lib/contrast/framework/rails/support.rb +2 -1
- data/lib/contrast/framework/sinatra/support.rb +3 -2
- data/lib/contrast/logger/application.rb +0 -3
- data/lib/contrast/utils/duck_utils.rb +1 -1
- data/lib/contrast/utils/heap_dump_util.rb +1 -1
- data/lib/contrast/utils/object_share.rb +3 -3
- data/lib/contrast/utils/preflight_util.rb +1 -1
- data/lib/contrast/utils/prevent_serialization.rb +1 -1
- data/lib/contrast/utils/resource_loader.rb +1 -1
- data/lib/contrast/utils/sha256_builder.rb +2 -2
- data/lib/contrast/utils/string_utils.rb +1 -1
- data/lib/contrast/utils/tag_util.rb +9 -13
- data/resources/assess/policy.json +9 -9
- data/resources/deadzone/policy.json +150 -0
- data/resources/protect/policy.json +12 -0
- data/ruby-agent.gemspec +10 -6
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +69 -25
|
@@ -12,7 +12,8 @@ module Contrast
|
|
|
12
12
|
module UserInput
|
|
13
13
|
UNKNOWN_USER_INPUT = Contrast::Api::Dtm::UserInput.new.tap do |user_input|
|
|
14
14
|
user_input.input_type = :UNKNOWN
|
|
15
|
-
end
|
|
15
|
+
end
|
|
16
|
+
UNKNOWN_USER_INPUT.cs__freeze
|
|
16
17
|
|
|
17
18
|
def self.included klass
|
|
18
19
|
klass.extend(ClassMethods)
|
|
@@ -65,7 +65,8 @@ module Contrast
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
%w[name default description required_languages display].each do |field|
|
|
68
|
-
|
|
68
|
+
# TODO: RUBY-1052
|
|
69
|
+
define_method(field) { hsh[field].dup } # rubocop:disable Performance/Kernel/DefineMethod
|
|
69
70
|
end
|
|
70
71
|
end
|
|
71
72
|
|
|
@@ -35,6 +35,42 @@ module Contrast
|
|
|
35
35
|
disabled_rules.include?(name)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# The value of the stacktrace should be treated as an ENUM. We upcase it for
|
|
39
|
+
# faster comparisons when we use it. Anything not one of the known values of
|
|
40
|
+
# 'NONE', 'SOME', or 'ALL' is treated as 'ALL'
|
|
41
|
+
#
|
|
42
|
+
# @return [Symbol] the normalized value of CONFIG.root.assess.stacktraces
|
|
43
|
+
def capture_stacktrace_value
|
|
44
|
+
@_capture_stacktrace_value ||= case CONFIG.root.assess.stacktraces.upcase
|
|
45
|
+
when 'NONE'
|
|
46
|
+
:NONE
|
|
47
|
+
when 'SOME'
|
|
48
|
+
:SOME
|
|
49
|
+
else
|
|
50
|
+
:ALL
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Consider capture_stacktrace_value along with the node type
|
|
55
|
+
# to dertmine whether stacktraces should be captured.
|
|
56
|
+
#
|
|
57
|
+
# capture_stacktrace_value -> (:ALL, :NONE, :SOME)
|
|
58
|
+
# node types (SourceNode, PolicyNode, TriggerNode, PropagationNode)
|
|
59
|
+
#
|
|
60
|
+
# @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode] The node in question.
|
|
61
|
+
# @param return [Boolean] to capture or not to capture, that is the question.
|
|
62
|
+
def capture_stacktrace? policy_node
|
|
63
|
+
return true if capture_stacktrace_value == :ALL
|
|
64
|
+
|
|
65
|
+
return false if capture_stacktrace_value == :NONE
|
|
66
|
+
|
|
67
|
+
# Below here capture_stacktrace_value must be :SOME.
|
|
68
|
+
return true if policy_node.cs__is_a?(Contrast::Agent::Assess::Policy::SourceNode)
|
|
69
|
+
return true if policy_node.cs__is_a?(Contrast::Agent::Assess::Policy::TriggerNode)
|
|
70
|
+
|
|
71
|
+
false
|
|
72
|
+
end
|
|
73
|
+
|
|
38
74
|
def scan_response?
|
|
39
75
|
@_scan_response = !false?(CONFIG.root.assess.enable_scan_response) if @_scan_response.nil?
|
|
40
76
|
@_scan_response
|
|
@@ -168,9 +168,11 @@ Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:settings]
|
|
|
168
168
|
require 'contrast/components/assess'
|
|
169
169
|
require 'contrast/components/protect'
|
|
170
170
|
require 'contrast/components/inventory'
|
|
171
|
-
Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:analysis] = [
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:analysis] = [
|
|
172
|
+
Contrast::Components::Protect,
|
|
173
|
+
Contrast::Components::Assess,
|
|
174
|
+
Contrast::Components::Inventory
|
|
175
|
+
]
|
|
174
176
|
|
|
175
177
|
require 'contrast/components/logger'
|
|
176
178
|
Contrast::Components::ComponentReceiverClassInterface::COMPONENT_MAP[:logging] = [Contrast::Components::Logger]
|
|
@@ -42,18 +42,84 @@ module Contrast
|
|
|
42
42
|
# For each instance method on a scope, define a forwarder
|
|
43
43
|
# to the scope on the current execution context's scope.
|
|
44
44
|
|
|
45
|
-
Contrast::Agent::Scope.public_instance_methods(false).each do |method_sym|
|
|
46
|
-
define_method(method_sym) do |*args, &block|
|
|
47
|
-
scope_for_current_ec.send(method_sym, *args, &block)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
45
|
def scope_for_current_ec
|
|
52
46
|
MONITOR.synchronize do
|
|
53
47
|
return EXECUTION_CONTEXT[Fiber.current] ||= Contrast::Agent::Scope.new
|
|
54
48
|
end
|
|
55
49
|
end
|
|
56
50
|
|
|
51
|
+
def enter_contrast_scope!
|
|
52
|
+
scope_for_current_ec.enter_contrast_scope!
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def enter_deserialization_scope!
|
|
56
|
+
scope_for_current_ec.enter_deserialization_scope!
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def enter_split_scope!
|
|
60
|
+
scope_for_current_ec.enter_split_scope!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def enter_scope! name
|
|
64
|
+
scope_for_current_ec.enter_scope! name
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def exit_contrast_scope!
|
|
68
|
+
scope_for_current_ec.exit_contrast_scope!
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def exit_deserialization_scope!
|
|
72
|
+
scope_for_current_ec.exit_deserialization_scope!
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def exit_split_scope!
|
|
76
|
+
scope_for_current_ec.exit_split_scope!
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def exit_scope! name
|
|
80
|
+
scope_for_current_ec.exit_scope! name
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def in_contrast_scope?
|
|
84
|
+
scope_for_current_ec.in_contrast_scope?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def in_deserialization_scope?
|
|
88
|
+
scope_for_current_ec.in_deserialization_scope?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def in_split_scope?
|
|
92
|
+
scope_for_current_ec.in_split_scope?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def split_scope_depth
|
|
96
|
+
scope_for_current_ec.split_scope_depth
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def in_scope? name
|
|
100
|
+
scope_for_current_ec.in_scope? name
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def with_contrast_scope
|
|
104
|
+
scope_for_current_ec.enter_contrast_scope!
|
|
105
|
+
yield
|
|
106
|
+
ensure
|
|
107
|
+
scope_for_current_ec.exit_contrast_scope!
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def with_deserialization_scope
|
|
111
|
+
scope_for_current_ec.enter_deserialization_scope!
|
|
112
|
+
ensure
|
|
113
|
+
scope_for_current_ec.exit_deserialization_scope!
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def with_split_scope
|
|
117
|
+
scope_for_current_ec.enter_split_scope!
|
|
118
|
+
yield
|
|
119
|
+
ensure
|
|
120
|
+
scope_for_current_ec.exit_split_scope!
|
|
121
|
+
end
|
|
122
|
+
|
|
57
123
|
# TODO: RUBY-572
|
|
58
124
|
#
|
|
59
125
|
# Current behavior is to no-op if we're not "in a request context".
|
|
@@ -57,19 +57,22 @@ module Contrast
|
|
|
57
57
|
# Meta-define an accessor for each state attribute.
|
|
58
58
|
|
|
59
59
|
PROTECT_STATE_ATTRS.each do |attr|
|
|
60
|
-
|
|
60
|
+
# TODO: RUBY-1052
|
|
61
|
+
define_method(attr) do # rubocop:disable Performance/Kernel/DefineMethod
|
|
61
62
|
protect_state[attr]
|
|
62
63
|
end
|
|
63
64
|
end
|
|
64
65
|
|
|
65
66
|
ASSESS_STATE_ATTRS.each do |attr|
|
|
66
|
-
|
|
67
|
+
# TODO: RUBY-1052
|
|
68
|
+
define_method(attr) do # rubocop:disable Performance/Kernel/DefineMethod
|
|
67
69
|
assess_state[attr]
|
|
68
70
|
end
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
APPLICATION_STATE_ATTRS.each do |attr|
|
|
72
|
-
|
|
74
|
+
# TODO: RUBY-1052
|
|
75
|
+
define_method(attr) do # rubocop:disable Performance/Kernel/DefineMethod
|
|
73
76
|
application_state[attr]
|
|
74
77
|
end
|
|
75
78
|
end
|
|
@@ -11,7 +11,8 @@ module Contrast
|
|
|
11
11
|
enable: EMPTY_VALUE,
|
|
12
12
|
enable_scan_response: Contrast::Config::DefaultValue.new('true'),
|
|
13
13
|
sampling: Contrast::Config::SamplingConfiguration,
|
|
14
|
-
rules: Contrast::Config::AssessRulesConfiguration
|
|
14
|
+
rules: Contrast::Config::AssessRulesConfiguration,
|
|
15
|
+
stacktraces: Contrast::Config::DefaultValue.new('ALL')
|
|
15
16
|
}.cs__freeze
|
|
16
17
|
|
|
17
18
|
def initialize hsh
|
|
@@ -35,12 +35,11 @@ module Contrast
|
|
|
35
35
|
# operation happens in C, we have to do it here rather than rely on the
|
|
36
36
|
# patch of our String append or concat methods.
|
|
37
37
|
def cs__track_join ary, separator, ret
|
|
38
|
-
return ret unless ary
|
|
38
|
+
return ret unless ary&.any? { |element| Contrast::Agent::Assess::Tracker.tracked?(element) }
|
|
39
39
|
return ret if Contrast::Agent::Patching::Policy::Patch.skip_assess_analysis?
|
|
40
40
|
|
|
41
41
|
with_contrast_scope do
|
|
42
|
-
properties = Contrast::Agent::Assess::Tracker.properties(ret)
|
|
43
|
-
return ret unless properties
|
|
42
|
+
return ret unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
|
|
44
43
|
|
|
45
44
|
shift = 0
|
|
46
45
|
separator_length = separator.nil? ? 0 : separator.to_s.length
|
|
@@ -6,9 +6,7 @@ module ERBPropagator
|
|
|
6
6
|
class << self
|
|
7
7
|
def result_tagger patcher, preshift, ret, _block
|
|
8
8
|
return unless preshift.args.length >= 1
|
|
9
|
-
|
|
10
|
-
properties = Contrast::Agent::Assess::Tracker.properties(ret)
|
|
11
|
-
return unless properties
|
|
9
|
+
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
|
|
12
10
|
|
|
13
11
|
used_binding = preshift.args[0]
|
|
14
12
|
binding_variable_set = used_binding.local_variables
|
|
@@ -27,10 +27,7 @@ module Contrast
|
|
|
27
27
|
source,
|
|
28
28
|
Kernel,
|
|
29
29
|
nil,
|
|
30
|
-
|
|
31
|
-
# Exec replaces the current process, if we occur in a forked process
|
|
32
|
-
# our appendage of this finding will not make it to TS
|
|
33
|
-
Contrast::Agent::AtExitHook.on_exit
|
|
30
|
+
source)
|
|
34
31
|
end
|
|
35
32
|
|
|
36
33
|
private
|
|
@@ -61,8 +61,7 @@ module Contrast
|
|
|
61
61
|
|
|
62
62
|
with_contrast_scope do
|
|
63
63
|
results.each do |result|
|
|
64
|
-
result_properties = Contrast::Agent::Assess::Tracker.properties(result)
|
|
65
|
-
next unless result_properties
|
|
64
|
+
next unless (result_properties = Contrast::Agent::Assess::Tracker.properties!(result))
|
|
66
65
|
|
|
67
66
|
result_properties.splat_from(fiber, result)
|
|
68
67
|
result_properties.build_event(
|
|
@@ -82,7 +81,7 @@ module Contrast
|
|
|
82
81
|
return unless underlying.is_a?(String) && !underlying.empty?
|
|
83
82
|
|
|
84
83
|
with_contrast_scope do
|
|
85
|
-
properties = Contrast::Agent::Assess::Tracker.properties(fiber)
|
|
84
|
+
properties = Contrast::Agent::Assess::Tracker.properties!(fiber)
|
|
86
85
|
return unless properties
|
|
87
86
|
|
|
88
87
|
properties.splat_from(underlying, fiber)
|
|
@@ -17,11 +17,13 @@ module Contrast
|
|
|
17
17
|
return object unless object.is_a?(String) && !object.cs__frozen?
|
|
18
18
|
return object unless Contrast::Agent::Assess::Tracker.tracked?(object)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
# Copy the object, then freeze it, so that it looks the same
|
|
21
|
+
# externally, but will have our finalizer on it.
|
|
22
|
+
object.dup&.cs__freeze
|
|
22
23
|
rescue StandardError
|
|
23
24
|
# we'll rescue this error, but we can't log it here as that will
|
|
24
25
|
# result in a seg fault
|
|
26
|
+
object
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def instrument_hash_track
|
|
@@ -39,8 +39,7 @@ module Contrast
|
|
|
39
39
|
# oh, and there's also %<name>type and %{name}... b/c of course there is
|
|
40
40
|
# -HM
|
|
41
41
|
def sprintf_tagger patcher, preshift, ret, _block
|
|
42
|
-
properties = Contrast::Agent::Assess::Tracker.properties(ret)
|
|
43
|
-
return unless properties
|
|
42
|
+
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
|
|
44
43
|
|
|
45
44
|
format_string = preshift.args[0]
|
|
46
45
|
args = preshift.args[1]
|
|
@@ -6,42 +6,50 @@ require 'contrast/components/interface'
|
|
|
6
6
|
module Contrast
|
|
7
7
|
module Extension
|
|
8
8
|
module Assess
|
|
9
|
-
# This is our patch of the
|
|
9
|
+
# This is our patch of the Marshal class
|
|
10
10
|
# Disclaimer: there may be a better way, but we're in a 'get it work' state.
|
|
11
11
|
# Hopefully, we'll be in a 'get it right' state soon.
|
|
12
|
-
# This module is used for our Marshal
|
|
12
|
+
# This module is used for our Marshal.load patches
|
|
13
13
|
class MarshalPropagator
|
|
14
14
|
include Contrast::Components::Interface
|
|
15
15
|
|
|
16
|
-
access_component :logging
|
|
16
|
+
access_component :logging, :scope
|
|
17
17
|
|
|
18
18
|
class << self
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
return unless current_context
|
|
19
|
+
def cs__load_protect arg
|
|
20
|
+
return if in_contrast_scope?
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
with_contrast_scope do
|
|
23
|
+
Contrast::Agent::Protect::Policy::AppliesDeserializationRule.prepended_invoke(arg)
|
|
24
|
+
end
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cs__load_assess source, ret
|
|
29
|
+
with_contrast_scope do
|
|
30
|
+
current_context = Contrast::Agent::REQUEST_TRACKER.current
|
|
31
|
+
return unless current_context
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
properties.copy_from(source, ret)
|
|
33
|
+
args = [source]
|
|
34
|
+
# source might not be all the args passed in, but it is the one we care
|
|
35
|
+
# about. we could pass in all the args in the last param here if it
|
|
36
|
+
# becomes an issue in rendering on TS
|
|
37
|
+
Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(
|
|
38
|
+
current_context,
|
|
39
|
+
trigger_node('Marshal', :load),
|
|
40
|
+
source,
|
|
41
|
+
self,
|
|
42
|
+
ret,
|
|
43
|
+
*args)
|
|
44
|
+
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
properties.copy_from(source, ret)
|
|
47
|
+
|
|
48
|
+
node = Contrast::Agent::Assess::Policy::Policy.instance.find_propagator_node('Marshal', :load, false)
|
|
49
|
+
properties.build_event(node, ret, self, ret, args)
|
|
50
|
+
rescue StandardError => e
|
|
51
|
+
logger.error('Unable to run Assess for Marshal.load', e)
|
|
52
|
+
end
|
|
45
53
|
end
|
|
46
54
|
|
|
47
55
|
def instrument_marshal_load
|
|
@@ -48,14 +48,9 @@ module Contrast
|
|
|
48
48
|
|
|
49
49
|
target = info_hash[:back_ref]
|
|
50
50
|
with_contrast_scope do
|
|
51
|
-
result = info_hash[:result]
|
|
52
|
-
return unless
|
|
53
|
-
|
|
54
|
-
string = info_hash[:string]
|
|
55
|
-
return unless string
|
|
56
|
-
|
|
57
|
-
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
|
58
|
-
return unless properties
|
|
51
|
+
return unless (result = info_hash[:result])
|
|
52
|
+
return unless (string = info_hash[:string])
|
|
53
|
+
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
|
|
59
54
|
|
|
60
55
|
properties.splat_from(string, target)
|
|
61
56
|
properties.build_event(
|
|
@@ -36,8 +36,7 @@ module Contrast
|
|
|
36
36
|
return unless inputs.any? { |input| Contrast::Agent::Assess::Tracker.tracked?(input) }
|
|
37
37
|
|
|
38
38
|
with_contrast_scope do
|
|
39
|
-
properties = Contrast::Agent::Assess::Tracker.properties(result)
|
|
40
|
-
return unless properties
|
|
39
|
+
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(result))
|
|
41
40
|
|
|
42
41
|
parent_events = []
|
|
43
42
|
offset = 0
|
|
@@ -4,68 +4,66 @@
|
|
|
4
4
|
module Contrast
|
|
5
5
|
module Framework
|
|
6
6
|
# The API for all subclasses to implement to correctly support a given framework
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end
|
|
7
|
+
module BaseSupport
|
|
8
|
+
# The top level module name used by the framework
|
|
9
|
+
def detection_class
|
|
10
|
+
raise NoMethodError('Subclasses of BaseSupport should implement this method')
|
|
11
|
+
end
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
def version
|
|
14
|
+
raise NoMethodError('Subclasses of BaseSupport should implement this method')
|
|
15
|
+
end
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
def application_name
|
|
18
|
+
raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
|
|
19
|
+
end
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
def server_type
|
|
22
|
+
raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
|
|
23
|
+
end
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
# Find all the predefined routes for this application and append them to the
|
|
26
|
+
# provided inventory message
|
|
27
|
+
# msg should be a Contrast::Api::Dtm::ApplicationUpdate or some other msg
|
|
28
|
+
# that has a routes array consisting of Contrast::Api::Dtm::RouteCoverage
|
|
29
|
+
def collect_routes
|
|
30
|
+
raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
|
|
31
|
+
end
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
def current_route
|
|
34
|
+
raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
|
|
35
|
+
end
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
def retrieve_request _env
|
|
38
|
+
raise NoMethodError, 'Subclasses of BaseSupport should implement this method'
|
|
39
|
+
end
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
# Some Frameworks require specific patching for their classes to handle
|
|
42
|
+
# functionality like configuration scanning. To accommodate this, this
|
|
43
|
+
# method provides a place to register those patches for invocation on
|
|
44
|
+
# Agent load.
|
|
45
|
+
#
|
|
46
|
+
# By default, and hopefully in all cases, we won't need these patches,
|
|
47
|
+
# so we're allowing nil here rather than raising an exception.
|
|
48
|
+
def before_load_patches!; end
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
# Some Frameworks require specific patching for their classes to handle
|
|
51
|
+
# functionality like routing. To accommodate this, this method provides
|
|
52
|
+
# a place to register those patches for invocation in our
|
|
53
|
+
# AfterLoadPatcher flow.
|
|
54
|
+
#
|
|
55
|
+
# By default, and hopefully in all cases, we won't need these patches,
|
|
56
|
+
# so we're allowing nil here rather than raising an exception.
|
|
57
|
+
#
|
|
58
|
+
# @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>,nil]
|
|
59
|
+
# those patches required for a Framework which can only be installed
|
|
60
|
+
# once a specific module has been loaded.
|
|
61
|
+
def after_load_patches; end
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
end
|
|
63
|
+
# We only support websockets in rails right now, so we won't detect streaming in
|
|
64
|
+
# any other framework
|
|
65
|
+
def streaming? _env
|
|
66
|
+
false
|
|
69
67
|
end
|
|
70
68
|
end
|
|
71
69
|
end
|