contrast-agent 4.2.0 → 4.3.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/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 +4 -4
- 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 +3 -3
- 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 +33 -13
- 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 +1 -1
- data/lib/contrast/components/assess.rb +36 -0
- data/lib/contrast/components/interface.rb +5 -3
- data/lib/contrast/components/scope.rb +23 -0
- data/lib/contrast/components/settings.rb +3 -3
- data/lib/contrast/config/assess_configuration.rb +2 -1
- data/lib/contrast/extension/assess/array.rb +1 -2
- data/lib/contrast/extension/assess/erb.rb +1 -3
- data/lib/contrast/extension/assess/exec_trigger.rb +1 -1
- 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 +1 -1
- 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/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 +156 -0
- data/resources/protect/policy.json +12 -0
- data/ruby-agent.gemspec +9 -6
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +68 -25
|
@@ -96,11 +96,11 @@ module Contrast
|
|
|
96
96
|
return unless method_exists?(clazz, method_name, type)
|
|
97
97
|
|
|
98
98
|
method_instance = method_instance(clazz, method_name, type)
|
|
99
|
-
return
|
|
99
|
+
return if method_instance.nil?
|
|
100
100
|
|
|
101
101
|
location = method_instance.source_location
|
|
102
|
-
return
|
|
103
|
-
return
|
|
102
|
+
return unless location_available?(location)
|
|
103
|
+
return if opener.written_from_location?(location)
|
|
104
104
|
|
|
105
105
|
opener.written_from_location!(location)
|
|
106
106
|
opener.source_code(location, method_name)
|
data/lib/contrast/agent/scope.rb
CHANGED
|
@@ -15,29 +15,40 @@ module Contrast
|
|
|
15
15
|
# Instead, we should say "If I'm already doing Contrast things, don't track
|
|
16
16
|
# this"
|
|
17
17
|
class Scope
|
|
18
|
-
SCOPE_LIST = %i[contrast deserialization].cs__freeze
|
|
18
|
+
SCOPE_LIST = %i[contrast deserialization split].cs__freeze
|
|
19
19
|
|
|
20
20
|
def initialize
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
@contrast_scope = 0
|
|
22
|
+
@deserialization_scope = 0
|
|
23
|
+
@split_scope = 0
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def in_contrast_scope?
|
|
26
|
-
|
|
27
|
+
@contrast_scope.positive?
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def in_deserialization_scope?
|
|
30
|
-
|
|
31
|
+
@deserialization_scope.positive?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def in_split_scope?
|
|
35
|
+
@split_scope.positive?
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
def enter_contrast_scope!
|
|
34
|
-
|
|
35
|
-
instance_variable_set(:@contrast_scope, level + 1)
|
|
39
|
+
@contrast_scope += 1
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
def enter_deserialization_scope!
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
@deserialization_scope += 1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def enter_split_scope!
|
|
47
|
+
@split_scope += 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def split_scope_depth
|
|
51
|
+
@split_scope
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
# Scope Exits...
|
|
@@ -61,13 +72,15 @@ module Contrast
|
|
|
61
72
|
# exit = 1
|
|
62
73
|
# scope = 1
|
|
63
74
|
def exit_contrast_scope!
|
|
64
|
-
|
|
65
|
-
instance_variable_set(:@contrast_scope, level - 1)
|
|
75
|
+
@contrast_scope -= 1
|
|
66
76
|
end
|
|
67
77
|
|
|
68
78
|
def exit_deserialization_scope!
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
@deserialization_scope -= 1
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def exit_split_scope!
|
|
83
|
+
@split_scope -= 1
|
|
71
84
|
end
|
|
72
85
|
|
|
73
86
|
def with_contrast_scope
|
|
@@ -84,6 +97,13 @@ module Contrast
|
|
|
84
97
|
exit_deserialization_scope!
|
|
85
98
|
end
|
|
86
99
|
|
|
100
|
+
def with_split_scope
|
|
101
|
+
enter_split_scope!
|
|
102
|
+
yield
|
|
103
|
+
ensure
|
|
104
|
+
exit_split_scope!
|
|
105
|
+
end
|
|
106
|
+
|
|
87
107
|
# Dynamic versions of the above.
|
|
88
108
|
# These are equivalent, but they're slower and riskier.
|
|
89
109
|
# Prefer the static methods if you know what scope you need at the call site.
|
|
@@ -17,14 +17,9 @@ module Contrast
|
|
|
17
17
|
# report the already-loaded gems.
|
|
18
18
|
def catchup
|
|
19
19
|
@_catchup ||= begin
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
send_inventory_message
|
|
23
|
-
true
|
|
24
|
-
end
|
|
20
|
+
threaded_analysis!
|
|
21
|
+
true
|
|
25
22
|
end
|
|
26
|
-
rescue StandardError => e
|
|
27
|
-
logger.warn('Unable to run post-initialization static analysis', e)
|
|
28
23
|
end
|
|
29
24
|
|
|
30
25
|
def send_inventory_message
|
|
@@ -35,6 +30,17 @@ module Contrast
|
|
|
35
30
|
Contrast::Utils::InventoryUtil.append_db_config(app_update_msg)
|
|
36
31
|
Contrast::Agent.messaging_queue.send_event_eventually(app_update_msg)
|
|
37
32
|
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def threaded_analysis!
|
|
37
|
+
Contrast::Agent::Thread.new do
|
|
38
|
+
Contrast::Agent::Inventory::DependencyUsageAnalysis.instance.catchup
|
|
39
|
+
send_inventory_message
|
|
40
|
+
rescue StandardError => e
|
|
41
|
+
logger.warn('Unable to run post-initialization static analysis', e)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
40
46
|
end
|
|
@@ -15,44 +15,30 @@ module Contrast
|
|
|
15
15
|
|
|
16
16
|
# Wrapper around build_event_object for the args array. Handles
|
|
17
17
|
# tainting the correct argument.
|
|
18
|
-
def build_event_args contrast_event, taint_target
|
|
18
|
+
def build_event_args! contrast_event, taint_target
|
|
19
19
|
contrast_event.args.each_index do |idx|
|
|
20
20
|
truncate_arg = taint_target != idx
|
|
21
21
|
event_arg = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.args[idx], truncate_arg)
|
|
22
22
|
args << event_arg
|
|
23
23
|
end
|
|
24
|
+
self
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
# TeamServer only supports one object's taint ranges at a time.
|
|
27
|
-
#
|
|
28
|
-
|
|
27
|
+
# TeamServer only supports one object's taint ranges at a time. We keep
|
|
28
|
+
# those tags on the event directly, so we just need to convert them to
|
|
29
|
+
# their DTM form in order to report this.
|
|
30
|
+
#
|
|
31
|
+
# @param contrast_event [Contrast::Agent::AssessContrastEvent]
|
|
32
|
+
def build_taint_ranges! contrast_event
|
|
29
33
|
# If there's no taint_target, this isn't a dataflow trace, but a
|
|
30
34
|
# trigger one
|
|
31
|
-
return
|
|
35
|
+
return self unless contrast_event&.tags
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Contrast::Agent::Assess::Tracker.properties(contrast_event.object)
|
|
36
|
-
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
37
|
-
Contrast::Agent::Assess::Tracker.properties(contrast_event.ret)
|
|
38
|
-
else
|
|
39
|
-
target = contrast_event.args[taint_target]
|
|
40
|
-
if target.is_a?(Hash)
|
|
41
|
-
if contrast_event.policy_node&.targets&.any?
|
|
42
|
-
Contrast::Agent::Assess::Tracker.properties(target[contrast_event.policy_node.targets[0]])
|
|
43
|
-
else
|
|
44
|
-
Contrast::Agent::Assess::Tracker.properties(target[contrast_event.policy_node.sources[0]])
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
Contrast::Agent::Assess::Tracker.properties(target)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
return unless properties.tracked?
|
|
51
|
-
|
|
52
|
-
self.taint_ranges += properties.tags_to_dtm
|
|
37
|
+
self.taint_ranges += Contrast::Api::Dtm::TraceTaintRange.build_for_event(contrast_event.tags)
|
|
38
|
+
self
|
|
53
39
|
end
|
|
54
40
|
|
|
55
|
-
def build_parent_ids contrast_event
|
|
41
|
+
def build_parent_ids! contrast_event
|
|
56
42
|
contrast_event&.parent_events&.each do |event|
|
|
57
43
|
next unless event
|
|
58
44
|
|
|
@@ -60,12 +46,14 @@ module Contrast
|
|
|
60
46
|
parent.id = event.event_id.to_i
|
|
61
47
|
parent_object_ids << parent
|
|
62
48
|
end
|
|
49
|
+
self
|
|
63
50
|
end
|
|
64
51
|
|
|
65
|
-
def build_stack contrast_event
|
|
52
|
+
def build_stack! contrast_event
|
|
66
53
|
# We delayed doing this as long as possible b/c it's expensive
|
|
67
54
|
stack_dtms = Contrast::Utils::StackTraceUtils.build_assess_stack_array(contrast_event.stack_trace)
|
|
68
55
|
self.stack += stack_dtms
|
|
56
|
+
self
|
|
69
57
|
end
|
|
70
58
|
|
|
71
59
|
# Class methods for TraceEvent
|
|
@@ -85,10 +73,10 @@ module Contrast
|
|
|
85
73
|
event_dtm.object = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.object, truncate_obj)
|
|
86
74
|
truncate_ret = Contrast::Utils::ObjectShare::RETURN_KEY != taint_target
|
|
87
75
|
event_dtm.ret = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.ret, truncate_ret)
|
|
88
|
-
event_dtm.build_event_args(contrast_event, taint_target)
|
|
89
|
-
event_dtm.build_parent_ids(contrast_event)
|
|
90
|
-
event_dtm.build_taint_ranges(contrast_event
|
|
91
|
-
event_dtm.build_stack(contrast_event)
|
|
76
|
+
event_dtm.build_event_args!(contrast_event, taint_target)
|
|
77
|
+
event_dtm.build_parent_ids!(contrast_event)
|
|
78
|
+
event_dtm.build_taint_ranges!(contrast_event)
|
|
79
|
+
event_dtm.build_stack!(contrast_event)
|
|
92
80
|
event_dtm.object_id = contrast_event.event_id.to_i
|
|
93
81
|
event_dtm.signature = Contrast::Api::Dtm::TraceEventSignature.build(contrast_event.ret, contrast_event.policy_node, contrast_event.args)
|
|
94
82
|
event_dtm
|
|
@@ -29,13 +29,21 @@ module Contrast
|
|
|
29
29
|
ELLIPSIS = '...'
|
|
30
30
|
UNTRUNCATED_PORTION_LENGTH = 25
|
|
31
31
|
TRUNCATION_LENGTH = (UNTRUNCATED_PORTION_LENGTH * 2) + ELLIPSIS.length
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
# Convert the given Object into a Contrast::Api::Dtm::TraceEventObject
|
|
34
|
+
#
|
|
35
|
+
# @param contrast_object [Contrast::Agent::Assess::ContrastObject, nil]
|
|
36
|
+
# the thing to convert, if any
|
|
37
|
+
# @param truncate [Boolean] if the converted object can/should be
|
|
38
|
+
# truncated.
|
|
39
|
+
# @return [Contrast::Api::Dtm::TraceEventObject]
|
|
40
|
+
def build contrast_object, truncate
|
|
33
41
|
event_object = new
|
|
34
42
|
with_contrast_scope do
|
|
35
|
-
obj_string = Contrast::Utils::StringUtils.force_utf8(object)
|
|
43
|
+
obj_string = Contrast::Utils::StringUtils.force_utf8(contrast_object&.object)
|
|
36
44
|
obj_string = truncate(obj_string) if truncate && obj_string.length > TRUNCATION_LENGTH
|
|
37
45
|
event_object.value = Base64.encode64(obj_string)
|
|
38
|
-
event_object.tracked =
|
|
46
|
+
event_object.tracked = contrast_object&.tracked?
|
|
39
47
|
end
|
|
40
48
|
event_object
|
|
41
49
|
end
|
|
@@ -17,27 +17,49 @@ module Contrast
|
|
|
17
17
|
|
|
18
18
|
# Class methods for TraceEventSignature
|
|
19
19
|
module ClassMethods
|
|
20
|
+
# Convert the given composites into components that TeamServer can
|
|
21
|
+
# understand in order to build a representation of the method
|
|
22
|
+
# invoked.
|
|
23
|
+
#
|
|
24
|
+
# @param ret_obj [Contrast::Agent::Assess::ContrastObject, nil] the
|
|
25
|
+
# return value of the method call.
|
|
26
|
+
# @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode]
|
|
27
|
+
# the policy which pertains to the method invoked.
|
|
28
|
+
# @param args [Array<Contrast::Agent::Assess::ContrastObject>, nil]
|
|
29
|
+
# @return [Contrast::Api::Dtm::TraceEventSignature]
|
|
20
30
|
def build ret_obj, policy_node, args
|
|
21
31
|
signature = new
|
|
22
|
-
return_type =
|
|
23
|
-
signature.return_type = Contrast::Utils::StringUtils.force_utf8(return_type)
|
|
32
|
+
signature.return_type = Contrast::Utils::StringUtils.force_utf8(type_name(ret_obj))
|
|
24
33
|
signature.class_name = Contrast::Utils::StringUtils.force_utf8(policy_node.class_name)
|
|
25
34
|
signature.method_name = Contrast::Utils::StringUtils.force_utf8(policy_node.method_name)
|
|
26
35
|
if args
|
|
27
36
|
args&.each do |arg|
|
|
28
|
-
|
|
29
|
-
signature.arg_types << Contrast::Utils::StringUtils.force_utf8(arg_type)
|
|
37
|
+
signature.arg_types << Contrast::Utils::StringUtils.force_utf8(type_name(arg))
|
|
30
38
|
end
|
|
31
39
|
end
|
|
32
40
|
signature.constructor = policy_node.method_name == :new
|
|
33
41
|
# if there's a ret, then this method isn't nil. not 100% full proof since you can
|
|
34
42
|
# return nil, but this is the best we've got currently.
|
|
35
|
-
signature.void_method = ret_obj.nil?
|
|
43
|
+
signature.void_method = ret_obj.nil? || ret_obj.object.nil?
|
|
36
44
|
# 8 is STATIC in Java... we have to placate them for now
|
|
37
45
|
# it has been requested that flags be removed since it isn't used
|
|
38
46
|
signature.flags = 8 unless policy_node.instance_method?
|
|
39
47
|
signature
|
|
40
48
|
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# While Ruby signatures do not require neither a return type and can
|
|
53
|
+
# return anything depending on inputs, code paths, etc, nor constant
|
|
54
|
+
# parameter types, TeamServer was designed with strongly typed
|
|
55
|
+
# languages (Java) in mind, so we need types in our signatures.
|
|
56
|
+
#
|
|
57
|
+
# @param contrast_object [Contrast::Agent::Assess::ContrastObject, nil]
|
|
58
|
+
# the object to find the type of
|
|
59
|
+
# @return [String] the name of the module of the ret_obj, or `nil`
|
|
60
|
+
def type_name contrast_object
|
|
61
|
+
contrast_object ? contrast_object.object_type : Contrast::Utils::ObjectShare::NIL_STRING
|
|
62
|
+
end
|
|
41
63
|
end
|
|
42
64
|
end
|
|
43
65
|
end
|
|
@@ -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)
|
|
@@ -66,7 +66,7 @@ module Contrast
|
|
|
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 Kernel/DefineMethod
|
|
69
|
+
define_method(field) { hsh[field].dup } # rubocop:disable Performance/Kernel/DefineMethod
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
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]
|
|
@@ -56,6 +56,10 @@ module Contrast
|
|
|
56
56
|
scope_for_current_ec.enter_deserialization_scope!
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
+
def enter_split_scope!
|
|
60
|
+
scope_for_current_ec.enter_split_scope!
|
|
61
|
+
end
|
|
62
|
+
|
|
59
63
|
def enter_scope! name
|
|
60
64
|
scope_for_current_ec.enter_scope! name
|
|
61
65
|
end
|
|
@@ -68,6 +72,10 @@ module Contrast
|
|
|
68
72
|
scope_for_current_ec.exit_deserialization_scope!
|
|
69
73
|
end
|
|
70
74
|
|
|
75
|
+
def exit_split_scope!
|
|
76
|
+
scope_for_current_ec.exit_split_scope!
|
|
77
|
+
end
|
|
78
|
+
|
|
71
79
|
def exit_scope! name
|
|
72
80
|
scope_for_current_ec.exit_scope! name
|
|
73
81
|
end
|
|
@@ -80,6 +88,14 @@ module Contrast
|
|
|
80
88
|
scope_for_current_ec.in_deserialization_scope?
|
|
81
89
|
end
|
|
82
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
|
+
|
|
83
99
|
def in_scope? name
|
|
84
100
|
scope_for_current_ec.in_scope? name
|
|
85
101
|
end
|
|
@@ -97,6 +113,13 @@ module Contrast
|
|
|
97
113
|
scope_for_current_ec.exit_deserialization_scope!
|
|
98
114
|
end
|
|
99
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
|
+
|
|
100
123
|
# TODO: RUBY-572
|
|
101
124
|
#
|
|
102
125
|
# Current behavior is to no-op if we're not "in a request context".
|