contrast-agent 4.6.0 → 4.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +1 -1
- data/Rakefile +1 -2
- data/ext/build_funchook.rb +3 -3
- data/ext/extconf_common.rb +1 -5
- data/lib/contrast/agent/assess.rb +1 -1
- data/lib/contrast/agent/assess/contrast_object.rb +2 -2
- data/lib/contrast/agent/assess/events/event_factory.rb +2 -1
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +6 -3
- data/lib/contrast/agent/assess/policy/patcher.rb +10 -17
- data/lib/contrast/agent/assess/policy/policy_node.rb +25 -33
- data/lib/contrast/agent/assess/policy/preshift.rb +3 -1
- data/lib/contrast/agent/assess/policy/propagation_method.rb +6 -15
- data/lib/contrast/agent/assess/policy/propagation_node.rb +19 -8
- data/lib/contrast/agent/assess/policy/propagator/center.rb +2 -1
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +3 -1
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +2 -1
- data/lib/contrast/agent/assess/policy/propagator/select.rb +2 -12
- data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -7
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -7
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +3 -15
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +6 -3
- data/lib/contrast/agent/assess/policy/source_method.rb +6 -6
- data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +1 -3
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +5 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +6 -15
- data/lib/contrast/agent/assess/policy/trigger_node.rb +2 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +4 -3
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -2
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -8
- data/lib/contrast/agent/assess/property/evented.rb +8 -5
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +11 -5
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +4 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +3 -5
- data/lib/contrast/agent/class_reopener.rb +3 -1
- data/lib/contrast/agent/disable_reaction.rb +1 -3
- data/lib/contrast/agent/exclusion_matcher.rb +5 -11
- data/lib/contrast/agent/inventory/dependencies.rb +2 -0
- data/lib/contrast/agent/middleware.rb +3 -5
- data/lib/contrast/agent/module_data.rb +3 -3
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +6 -5
- data/lib/contrast/agent/patching/policy/method_policy.rb +6 -2
- data/lib/contrast/agent/patching/policy/module_policy.rb +14 -7
- data/lib/contrast/agent/patching/policy/patch.rb +11 -16
- data/lib/contrast/agent/patching/policy/patch_status.rb +6 -7
- data/lib/contrast/agent/patching/policy/patcher.rb +15 -12
- data/lib/contrast/agent/patching/policy/policy_node.rb +14 -4
- data/lib/contrast/agent/patching/policy/trigger_node.rb +21 -8
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +2 -3
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +5 -9
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +5 -5
- data/lib/contrast/agent/protect/rule/base.rb +13 -16
- data/lib/contrast/agent/protect/rule/base_service.rb +9 -5
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +14 -18
- data/lib/contrast/agent/protect/rule/deserialization.rb +6 -13
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +3 -14
- data/lib/contrast/agent/protect/rule/no_sqli.rb +6 -2
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -3
- data/lib/contrast/agent/protect/rule/path_traversal.rb +5 -5
- data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +1 -1
- data/lib/contrast/agent/protect/rule/xss.rb +1 -1
- data/lib/contrast/agent/protect/rule/xxe.rb +5 -12
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +1 -2
- data/lib/contrast/agent/reaction_processor.rb +11 -10
- data/lib/contrast/agent/request.rb +23 -23
- data/lib/contrast/agent/request_context.rb +9 -14
- data/lib/contrast/agent/rewriter.rb +5 -3
- data/lib/contrast/agent/service_heartbeat.rb +2 -3
- data/lib/contrast/agent/tracepoint_hook.rb +1 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/communication/response_processor.rb +2 -4
- data/lib/contrast/api/communication/service_lifecycle.rb +4 -2
- data/lib/contrast/api/communication/socket_client.rb +8 -21
- data/lib/contrast/api/communication/speedracer.rb +3 -7
- data/lib/contrast/api/decorators/application_startup.rb +6 -2
- data/lib/contrast/api/decorators/library.rb +8 -6
- data/lib/contrast/api/decorators/message.rb +3 -3
- data/lib/contrast/api/decorators/trace_event.rb +3 -1
- data/lib/contrast/api/decorators/trace_event_object.rb +1 -3
- data/lib/contrast/api/decorators/trace_taint_range_tags.rb +1 -6
- data/lib/contrast/components/agent.rb +9 -4
- data/lib/contrast/components/app_context.rb +6 -6
- data/lib/contrast/components/config.rb +2 -1
- data/lib/contrast/components/contrast_service.rb +7 -8
- data/lib/contrast/components/interface.rb +3 -2
- data/lib/contrast/components/sampling.rb +8 -2
- data/lib/contrast/components/settings.rb +4 -2
- data/lib/contrast/config/assess_rules_configuration.rb +1 -3
- data/lib/contrast/config/base_configuration.rb +4 -5
- data/lib/contrast/config/exception_configuration.rb +1 -5
- data/lib/contrast/config/heap_dump_configuration.rb +12 -6
- data/lib/contrast/config/logger_configuration.rb +1 -5
- data/lib/contrast/configuration.rb +3 -14
- data/lib/contrast/extension/assess/array.rb +1 -6
- data/lib/contrast/extension/assess/erb.rb +1 -7
- data/lib/contrast/extension/assess/eval_trigger.rb +2 -6
- data/lib/contrast/extension/assess/exec_trigger.rb +3 -9
- data/lib/contrast/extension/assess/fiber.rb +2 -12
- data/lib/contrast/extension/assess/kernel.rb +2 -9
- data/lib/contrast/extension/assess/marshal.rb +2 -6
- data/lib/contrast/extension/assess/regexp.rb +1 -6
- data/lib/contrast/extension/assess/string.rb +3 -1
- data/lib/contrast/extension/kernel.rb +4 -2
- data/lib/contrast/framework/manager.rb +1 -2
- data/lib/contrast/framework/rack/patch/session_cookie.rb +5 -18
- data/lib/contrast/framework/rack/patch/support.rb +6 -4
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +7 -2
- data/lib/contrast/framework/rails/patch/support.rb +4 -2
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +4 -1
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +2 -0
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +2 -0
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +2 -0
- data/lib/contrast/framework/rails/support.rb +2 -2
- data/lib/contrast/framework/sinatra/support.rb +3 -1
- data/lib/contrast/funchook/funchook.rb +1 -5
- data/lib/contrast/logger/application.rb +12 -9
- data/lib/contrast/logger/format.rb +2 -5
- data/lib/contrast/logger/log.rb +4 -3
- data/lib/contrast/logger/request.rb +1 -2
- data/lib/contrast/security_exception.rb +1 -1
- data/lib/contrast/tasks/service.rb +5 -1
- data/lib/contrast/utils/assess/tracking_util.rb +1 -2
- data/lib/contrast/utils/class_util.rb +0 -8
- data/lib/contrast/utils/hash_digest.rb +2 -5
- data/lib/contrast/utils/io_util.rb +1 -1
- data/lib/contrast/utils/job_servers_running.rb +9 -4
- data/lib/contrast/utils/os.rb +2 -1
- data/lib/contrast/utils/ruby_ast_rewriter.rb +2 -1
- data/ruby-agent.gemspec +13 -14
- data/sonar-project.properties +9 -0
- metadata +37 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b3d1ce6b9794d3923d2054d9a20bd31989fd0c6b4df2883f81ad3e740c04de5
|
4
|
+
data.tar.gz: 894505c04e850858f83e2207c52cc944f738ce19183051d9530cfdaf09f72ab7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4df81e8b3d03efcdc952e9fce5330b34c6af6a965701ec7bbe02cf3dbd5b8a3c98d8d0745da91d7b0a43be6b03ac763ffb6e9eafb9f2b857bd2a76d325d10ad2
|
7
|
+
data.tar.gz: 0015e74007146cf741e6b7f6274460a948a147df54109de959856f0ff883262260685f74eff8767e6ae845847eaf3d8a17dfbd54061d5b9f561952a8c6b90fef
|
data/.gitmodules
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
[submodule "agent-service-api"]
|
2
2
|
path = agent-service-api
|
3
|
-
url = git@
|
3
|
+
url = git@github.com:Contrast-Security-Inc/agent-service-api.git
|
4
4
|
[submodule "funchook"]
|
5
5
|
path = funchook
|
6
6
|
url = https://github.com/kubo/funchook.git
|
data/Rakefile
CHANGED
@@ -23,8 +23,7 @@ task :contrast_pb_compile do
|
|
23
23
|
# do some stuff before compile
|
24
24
|
|
25
25
|
# Invoke the protobuf compile task with your sensible defaults
|
26
|
-
::Rake::Task['protobuf:compile'].invoke('lib',
|
27
|
-
'./agent-service-api/protobuf ./agent-service-api/protobuf/dtm.proto',
|
26
|
+
::Rake::Task['protobuf:compile'].invoke('lib', './agent-service-api/protobuf ./agent-service-api/protobuf/dtm.proto',
|
28
27
|
'lib/contrast/api',
|
29
28
|
nil)
|
30
29
|
|
data/ext/build_funchook.rb
CHANGED
@@ -10,7 +10,8 @@ unless find_header('funchook.h', ext_path)
|
|
10
10
|
COMMANDS = ['./autogen.sh', './configure', 'make clean', 'make'].freeze
|
11
11
|
bundler_install_target_paths = []
|
12
12
|
|
13
|
-
|
13
|
+
# .path and .paths diverge in their return type - .path returns strings, .paths returns PathSupports
|
14
|
+
possible_gem_paths = Gem.path
|
14
15
|
possible_gem_paths.each do |base_path|
|
15
16
|
contrast_gem_dir_search = File.join(base_path, 'extensions', '**', '*', 'contrast-agent-*')
|
16
17
|
extension_paths = Dir[contrast_gem_dir_search]
|
@@ -31,8 +32,7 @@ unless find_header('funchook.h', ext_path)
|
|
31
32
|
end
|
32
33
|
|
33
34
|
SOURCE_PATHS = [
|
34
|
-
File.join('include', 'funchook.h'),
|
35
|
-
File.join('src', 'libfunchook.dylib'),
|
35
|
+
File.join('include', 'funchook.h'), File.join('src', 'libfunchook.dylib'),
|
36
36
|
File.join('src', 'libfunchook.so')
|
37
37
|
].freeze
|
38
38
|
|
data/ext/extconf_common.rb
CHANGED
@@ -10,7 +10,7 @@ module Contrast
|
|
10
10
|
module Assess
|
11
11
|
require 'contrast/agent/assess/tracker'
|
12
12
|
require 'contrast/agent/module_data'
|
13
|
-
require 'contrast/agent/rewriter'
|
13
|
+
require 'contrast/agent/rewriter' if RUBY_VERSION < '2.6.0' # TODO: RUBY-714 remove guard w/ EOL of 2.5
|
14
14
|
require 'contrast/agent/assess/policy/preshift'
|
15
15
|
|
16
16
|
# Dynamic Sources
|
@@ -34,14 +34,14 @@ module Contrast
|
|
34
34
|
def initialize object
|
35
35
|
if object
|
36
36
|
@object = Contrast::Utils::ClassUtil.to_contrast_string(object)
|
37
|
-
@object_type = object.cs__class.
|
37
|
+
@object_type = object.cs__class.cs__name
|
38
38
|
# TODO: RUBY-1084 determine if we need to copy these tags to
|
39
39
|
# restore immutability. For instance, if these tags were on a
|
40
40
|
# String that was then #reverse!'d, would our tags be wrong?
|
41
41
|
@tags = Contrast::Agent::Assess::Tracker.properties(object)&.tags
|
42
42
|
else
|
43
43
|
@object = Contrast::Utils::ObjectShare::NIL_STRING
|
44
|
-
@object_type = nil.cs__class.
|
44
|
+
@object_type = nil.cs__class.cs__name
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -13,7 +13,8 @@ module Contrast
|
|
13
13
|
def self.build policy_node, tagged, object, ret, args, source_type = nil, source_name = nil
|
14
14
|
case policy_node
|
15
15
|
when Contrast::Agent::Assess::Policy::SourceNode
|
16
|
-
Contrast::Agent::Assess::Events::SourceEvent.new(policy_node, tagged, object, ret, args, source_type,
|
16
|
+
Contrast::Agent::Assess::Events::SourceEvent.new(policy_node, tagged, object, ret, args, source_type,
|
17
|
+
source_name)
|
17
18
|
when Contrast::Agent::Assess::Policy::PolicyNode
|
18
19
|
Contrast::Agent::Assess::ContrastEvent.new(policy_node, tagged, object, ret, args)
|
19
20
|
end
|
@@ -37,7 +37,8 @@ module Contrast
|
|
37
37
|
# Move on if we already know about this Dynamic Source
|
38
38
|
next if Contrast::Agent::Assess::Policy::Policy.instance.find_source_node(class_name, method_name, true)
|
39
39
|
|
40
|
-
dynamic_source_node = create_source_node(class_name, method_name, Set.new(properties.tag_keys),
|
40
|
+
dynamic_source_node = create_source_node(class_name, method_name, Set.new(properties.tag_keys),
|
41
|
+
current_request)
|
41
42
|
Contrast::Agent::Assess::Policy::Policy.instance.add_node(dynamic_source_node, :dynamic_source)
|
42
43
|
method_policy = build_source_policy(method_name, dynamic_source_node)
|
43
44
|
Contrast::Agent::Patching::Policy::Patcher.patch_method(klass, instance_methods, method_policy)
|
@@ -130,8 +131,10 @@ module Contrast
|
|
130
131
|
def append_properties! dynamic_source, request, source_node, field
|
131
132
|
dynamic_source.properties[READ_TABLE] = Contrast::Utils::StringUtils.force_utf8(source_node.class_name)
|
132
133
|
dynamic_source.properties[READ_COLUMN] = Contrast::Utils::StringUtils.force_utf8(field)
|
133
|
-
dynamic_source.properties[WRITE_QUERY_TIME] =
|
134
|
-
|
134
|
+
dynamic_source.properties[WRITE_QUERY_TIME] =
|
135
|
+
Contrast::Utils::StringUtils.force_utf8(Contrast::Utils::Timer.now_ms)
|
136
|
+
dynamic_source.properties[WRITE_QUERY_URL] =
|
137
|
+
Contrast::Utils::StringUtils.force_utf8(request&.normalized_uri)
|
135
138
|
end
|
136
139
|
|
137
140
|
def append_events! dynamic_source, event
|
@@ -39,19 +39,13 @@ module Contrast
|
|
39
39
|
|
40
40
|
patcher.patch_specific_module(mod)
|
41
41
|
rescue StandardError => e
|
42
|
-
logger.warn(
|
43
|
-
'Unable to patch assess during eval',
|
44
|
-
e,
|
45
|
-
module: mod.cs__name)
|
42
|
+
logger.warn('Unable to patch assess during eval', e, module: mod.cs__name)
|
46
43
|
end
|
47
44
|
|
48
45
|
# Exposed so that methods can be dynamically patched on creation at
|
49
46
|
# runtime, like those generated by
|
50
47
|
# ActiveRecord::AttributeMethods::Read::ClassMethods#define_method_attribute
|
51
|
-
CLASS_TYPES = [
|
52
|
-
Contrast::Utils::ObjectShare::CLASS,
|
53
|
-
Contrast::Utils::ObjectShare::MODULE
|
54
|
-
].cs__freeze
|
48
|
+
CLASS_TYPES = [Contrast::Utils::ObjectShare::CLASS, Contrast::Utils::ObjectShare::MODULE].cs__freeze
|
55
49
|
def patch_assess_method mod, method_name
|
56
50
|
# Module.define_method is called a lot in Class and Module. We
|
57
51
|
# currently do not expect these define_methods to result in methods
|
@@ -62,7 +56,8 @@ module Contrast
|
|
62
56
|
return if CLASS_TYPES.include?(class_name)
|
63
57
|
return unless ASSESS.enabled?
|
64
58
|
|
65
|
-
source_nodes = Contrast::Agent::Patching::Policy::ModulePolicy.nodes_for_module(policy.sources,
|
59
|
+
source_nodes = Contrast::Agent::Patching::Policy::ModulePolicy.nodes_for_module(policy.sources,
|
60
|
+
class_name)
|
66
61
|
return if source_nodes.empty?
|
67
62
|
|
68
63
|
method_array = []
|
@@ -70,17 +65,15 @@ module Contrast
|
|
70
65
|
source_nodes.each do |source_node|
|
71
66
|
next unless source_node.method_name.to_s == method_name
|
72
67
|
|
73
|
-
method_policy =
|
74
|
-
|
75
|
-
|
76
|
-
|
68
|
+
method_policy =
|
69
|
+
Contrast::Agent::Patching::Policy::MethodPolicy.new(source_node: source_node,
|
70
|
+
method_name: source_node.method_name,
|
71
|
+
method_visibility: source_node.method_visibility,
|
72
|
+
instance_method: true)
|
77
73
|
patcher.patch_method(mod, method_array, method_policy)
|
78
74
|
end
|
79
75
|
rescue StandardError => e
|
80
|
-
logger.warn(
|
81
|
-
'Unable to patch assess during define_method_attribute',
|
82
|
-
e,
|
83
|
-
module: mod.cs__name)
|
76
|
+
logger.warn('Unable to patch assess during define_method_attribute', e, module: mod.cs__name)
|
84
77
|
end
|
85
78
|
end
|
86
79
|
end
|
@@ -35,16 +35,6 @@ module Contrast
|
|
35
35
|
:TYPE_METHOD
|
36
36
|
end
|
37
37
|
|
38
|
-
def target
|
39
|
-
@_target ||= begin
|
40
|
-
if targets&.any?
|
41
|
-
targets[0]
|
42
|
-
elsif sources&.any?
|
43
|
-
sources[0]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
38
|
def target_string= value
|
49
39
|
@target_string = value
|
50
40
|
@targets = convert_policy_markers(value)
|
@@ -85,8 +75,7 @@ module Contrast
|
|
85
75
|
next if Contrast::Api::Decorators::TraceTaintRangeTags::VALID_TAGS.include?(tag) ||
|
86
76
|
Contrast::Api::Decorators::TraceTaintRangeTags::VALID_SOURCE_TAGS.include?(tag)
|
87
77
|
|
88
|
-
raise(ArgumentError,
|
89
|
-
"#{ node_class } #{ id } had an invalid tag. #{ tag } is not a known value.")
|
78
|
+
raise(ArgumentError, "#{ node_class } #{ id } had an invalid tag. #{ tag } is not a known value.")
|
90
79
|
end
|
91
80
|
end
|
92
81
|
|
@@ -100,27 +89,26 @@ module Contrast
|
|
100
89
|
# Trigger (trigger nodes) don't have targets (they are the target)
|
101
90
|
# Everything else (propagation nodes) are Source2Target
|
102
91
|
def build_action
|
103
|
-
@event_action ||=
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
end
|
92
|
+
@event_action ||= case node_class
|
93
|
+
when Contrast::Agent::Assess::Policy::SourceNode::SOURCE
|
94
|
+
:CREATION
|
95
|
+
when Contrast::Agent::Assess::Policy::TriggerNode::TRIGGER
|
96
|
+
:TRIGGER
|
97
|
+
else
|
98
|
+
if source_string.nil?
|
99
|
+
:CREATION
|
100
|
+
elsif target_string.nil?
|
101
|
+
:TRIGGER
|
102
|
+
else
|
103
|
+
# TeamServer can't handle the multi-source or multi-target values. Give it some help
|
104
|
+
# by changing them to 'A'
|
105
|
+
source = all_type?(source_string) ? ALL_TYPE : source_string
|
106
|
+
target = all_type?(target_string) ? ALL_TYPE : target_string
|
107
|
+
str = source[0] + TO_MARKER + target[0]
|
108
|
+
str.to_sym
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
124
112
|
@event_action
|
125
113
|
end
|
126
114
|
|
@@ -158,6 +146,10 @@ module Contrast
|
|
158
146
|
end
|
159
147
|
converted
|
160
148
|
end
|
149
|
+
|
150
|
+
def all_type? marker
|
151
|
+
marker.include?(Contrast::Utils::ObjectShare::COMMA)
|
152
|
+
end
|
161
153
|
end
|
162
154
|
end
|
163
155
|
end
|
@@ -91,7 +91,9 @@ module Contrast
|
|
91
91
|
|
92
92
|
Contrast::Agent::Assess::Tracker.copy(original_arg, preshift_arg)
|
93
93
|
end
|
94
|
-
preshift.arg_lengths = preshift.args.map
|
94
|
+
preshift.arg_lengths = preshift.args.map do |preshift_arg|
|
95
|
+
Contrast::Utils::DuckUtils.quacks_to?(preshift_arg, :length) ? preshift_arg.length : 0
|
96
|
+
end
|
95
97
|
end
|
96
98
|
end
|
97
99
|
end
|
@@ -140,13 +140,7 @@ module Contrast
|
|
140
140
|
!!target
|
141
141
|
end
|
142
142
|
|
143
|
-
ZERO_LENGTH_ACTIONS = [
|
144
|
-
DB_WRITE_ACTION,
|
145
|
-
CUSTOM_ACTION,
|
146
|
-
KEEP_ACTION,
|
147
|
-
REPLACE_ACTION,
|
148
|
-
SPLAT_ACTION
|
149
|
-
].cs__freeze
|
143
|
+
ZERO_LENGTH_ACTIONS = [DB_WRITE_ACTION, CUSTOM_ACTION, KEEP_ACTION, REPLACE_ACTION, SPLAT_ACTION].cs__freeze
|
150
144
|
# If the action required needs a length and the target does not have
|
151
145
|
# one, the length is not valid
|
152
146
|
def valid_length? target, action
|
@@ -245,7 +239,7 @@ module Contrast
|
|
245
239
|
|
246
240
|
def handle_enumerable_propagation propagation_node, preshift, target, object, ret, args, block
|
247
241
|
target.each do |value|
|
248
|
-
next if target == value
|
242
|
+
next if target == value
|
249
243
|
|
250
244
|
apply_propagator(propagation_node, preshift, value, object, ret, args, block)
|
251
245
|
end
|
@@ -283,9 +277,7 @@ module Contrast
|
|
283
277
|
|
284
278
|
properties.add_properties(propagation_node.properties)
|
285
279
|
properties.build_event(propagation_node, target, object, ret, args)
|
286
|
-
logger.trace('Propagation detected',
|
287
|
-
node_id: propagation_node.id,
|
288
|
-
target_id: target.__id__)
|
280
|
+
logger.trace('Propagation detected', node_id: propagation_node.id, target_id: target.__id__)
|
289
281
|
restore_frozen_state ? ret : nil
|
290
282
|
end
|
291
283
|
|
@@ -296,10 +288,9 @@ module Contrast
|
|
296
288
|
# @return [Contrast::Agent::Assess::Policy::Propagator, nil]
|
297
289
|
def find_propagation_class propagation_node
|
298
290
|
unless (propagation_class = PROPAGATION_ACTIONS.fetch(propagation_node.action, nil))
|
299
|
-
logger.warn(
|
300
|
-
|
301
|
-
|
302
|
-
action: propagation_node.action)
|
291
|
+
logger.warn('Unknown propagation action received. Unable to propagate.',
|
292
|
+
node_id: propagation_node.id,
|
293
|
+
action: propagation_node.action)
|
303
294
|
end
|
304
295
|
propagation_class
|
305
296
|
end
|
@@ -62,11 +62,19 @@ module Contrast
|
|
62
62
|
raise(ArgumentError, "Propagator #{ id } did not have a proper action. Unable to create.") unless action
|
63
63
|
|
64
64
|
if @action == 'CUSTOM'
|
65
|
-
|
66
|
-
|
65
|
+
unless patch_class
|
66
|
+
raise(ArgumentError, "Propagator #{ id } did not have a proper patch_class. Unable to create.")
|
67
|
+
end
|
68
|
+
unless patch_method.is_a?(Symbol)
|
69
|
+
raise(ArgumentError, "Propagator #{ id } did not have a proper patch_method. Unable to create.")
|
70
|
+
end
|
67
71
|
else
|
68
|
-
|
69
|
-
|
72
|
+
unless targets&.any?
|
73
|
+
raise(ArgumentError, "Propagator #{ id } did not have a proper target. Unable to create.")
|
74
|
+
end
|
75
|
+
unless sources&.any?
|
76
|
+
raise(ArgumentError, "Propagator #{ id } did not have a proper source. Unable to create.")
|
77
|
+
end
|
70
78
|
end
|
71
79
|
validate_untags
|
72
80
|
end
|
@@ -76,9 +84,12 @@ module Contrast
|
|
76
84
|
|
77
85
|
untags.each do |tag|
|
78
86
|
unless Contrast::Api::Decorators::TraceTaintRangeTags::VALID_TAGS.include?(tag)
|
79
|
-
raise(ArgumentError,
|
87
|
+
raise(ArgumentError,
|
88
|
+
"#{ node_type } #{ id } did not have a valid untag. #{ tag } is not a known value.")
|
89
|
+
end
|
90
|
+
if tags&.include?(tag)
|
91
|
+
raise(ArgumentError, "#{ node_type } #{ id } had the same tag and untag, #{ tag }.")
|
80
92
|
end
|
81
|
-
raise(ArgumentError, "#{ node_type } #{ id } had the same tag and untag, #{ tag }.") if tags&.include?(tag)
|
82
93
|
end
|
83
94
|
end
|
84
95
|
|
@@ -86,8 +97,8 @@ module Contrast
|
|
86
97
|
if @_needs_object.nil?
|
87
98
|
@_needs_object = action == Contrast::Agent::Assess::Policy::PropagationMethod::CUSTOM_ACTION ||
|
88
99
|
action == Contrast::Agent::Assess::Policy::PropagationMethod::DB_WRITE_ACTION ||
|
89
|
-
sources.any?
|
90
|
-
targets.any?
|
100
|
+
sources.any?(Contrast::Utils::ObjectShare::OBJECT_KEY) ||
|
101
|
+
targets.any?(Contrast::Utils::ObjectShare::OBJECT_KEY)
|
91
102
|
end
|
92
103
|
@_needs_object
|
93
104
|
end
|
@@ -31,7 +31,8 @@ module Contrast
|
|
31
31
|
return unless sources[1]
|
32
32
|
|
33
33
|
original_end_index = original_start_index + source1.length - 1
|
34
|
-
handle_incoming_tags(target, propagation_node, sources[1], preshift, original_start_index,
|
34
|
+
handle_incoming_tags(target, propagation_node, sources[1], preshift, original_start_index,
|
35
|
+
original_end_index)
|
35
36
|
end
|
36
37
|
|
37
38
|
private
|
@@ -33,7 +33,9 @@ module Contrast
|
|
33
33
|
# point on which all tags need to be adjusted
|
34
34
|
# If the insertion point is the end of the string, preshift length is returned
|
35
35
|
# https://stackoverflow.com/questions/31714522/find-the-first-differing-character-between-two-strings-in-ruby
|
36
|
-
insert_point = (0...preshift_target.length).find
|
36
|
+
insert_point = (0...preshift_target.length).find do |i|
|
37
|
+
preshift_target[i] != target[i]
|
38
|
+
end || preshift_target.length
|
37
39
|
# Depending what's inserted, we might be wrong. For instance, inserting 'foo'
|
38
40
|
# into 'asdfasdf' could result in 'asdfoofasdf'. we'd be off by one b/c of the 'f'
|
39
41
|
insert_point = target.rindex(source, insert_point)
|
@@ -76,7 +76,8 @@ module Contrast
|
|
76
76
|
applicable_tags.each do |tag_name, tag_ranges|
|
77
77
|
return_properties.set_tags(tag_name, tag_ranges)
|
78
78
|
end
|
79
|
-
return_properties.build_event(propagation_node, return_value, preshift.object, return_value,
|
79
|
+
return_properties.build_event(propagation_node, return_value, preshift.object, return_value,
|
80
|
+
preshift.args)
|
80
81
|
end
|
81
82
|
end
|
82
83
|
end
|
@@ -21,22 +21,12 @@ module Contrast
|
|
21
21
|
# Additionally, an empty string is returned when the starting index for
|
22
22
|
# a character range is at the end of the string. Let's just skip that
|
23
23
|
# and only track a string that has length
|
24
|
-
unless ret &&
|
25
|
-
!ret.empty? &&
|
26
|
-
Contrast::Agent::Assess::Tracker.tracked?(source)
|
27
|
-
|
28
|
-
return
|
29
|
-
end
|
24
|
+
return unless ret && !ret.empty? && Contrast::Agent::Assess::Tracker.tracked?(source)
|
30
25
|
|
31
26
|
return unless (source_properties = Contrast::Agent::Assess::Tracker.properties(source))
|
32
27
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
|
33
28
|
|
34
|
-
properties.build_event(
|
35
|
-
patcher,
|
36
|
-
ret,
|
37
|
-
source,
|
38
|
-
ret,
|
39
|
-
args)
|
29
|
+
properties.build_event(patcher, ret, source, ret, args)
|
40
30
|
|
41
31
|
range = determine_select_range(source, args)
|
42
32
|
return unless range
|
@@ -31,9 +31,7 @@ module Contrast
|
|
31
31
|
# @return [nil] so as not to risk changing the result of the propagation.
|
32
32
|
|
33
33
|
def propagate propagation_node, preshift, target
|
34
|
-
logger.trace('Propagation detected',
|
35
|
-
node_id: propagation_node.id,
|
36
|
-
target_id: target.__id__)
|
34
|
+
logger.trace('Propagation detected', node_id: propagation_node.id, target_id: target.__id__)
|
37
35
|
|
38
36
|
source = find_source(propagation_node.sources[0], preshift)
|
39
37
|
return unless (source_properties = Contrast::Agent::Assess::Tracker.properties(source))
|
@@ -162,10 +160,8 @@ module Contrast
|
|
162
160
|
#
|
163
161
|
# @return [Contrast::Agent::Assess::Policy::PropagationNode] String#split node
|
164
162
|
def split_node
|
165
|
-
@_split_node ||=
|
166
|
-
|
167
|
-
node.class_name == 'String' && node.method_name == :split && node.instance_method?
|
168
|
-
end
|
163
|
+
@_split_node ||= Contrast::Agent::Assess::Policy::Policy.instance.propagators.find do |node|
|
164
|
+
node.class_name == 'String' && node.method_name == :split && node.instance_method?
|
169
165
|
end
|
170
166
|
end
|
171
167
|
end
|