contrast-agent 4.6.0 → 4.7.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/.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
|