contrast-agent 4.3.2 → 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/.simplecov +1 -1
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/Rakefile +2 -3
- data/exe/contrast_service +1 -1
- data/ext/build_funchook.rb +4 -4
- data/ext/cs__assess_active_record_named/cs__active_record_named.c +1 -1
- data/ext/cs__assess_active_record_named/extconf.rb +1 -1
- data/ext/cs__assess_array/cs__assess_array.c +1 -1
- data/ext/cs__assess_array/extconf.rb +1 -1
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +1 -1
- data/ext/cs__assess_basic_object/extconf.rb +1 -1
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
- data/ext/cs__assess_fiber_track/extconf.rb +1 -1
- data/ext/cs__assess_hash/cs__assess_hash.c +4 -2
- data/ext/cs__assess_hash/extconf.rb +1 -1
- data/ext/cs__assess_kernel/cs__assess_kernel.c +1 -1
- data/ext/cs__assess_kernel/extconf.rb +1 -1
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +1 -1
- data/ext/cs__assess_marshal_module/extconf.rb +1 -1
- data/ext/cs__assess_module/cs__assess_module.c +1 -1
- data/ext/cs__assess_module/extconf.rb +1 -1
- data/ext/cs__assess_regexp/cs__assess_regexp.c +1 -1
- data/ext/cs__assess_regexp/extconf.rb +1 -1
- data/ext/cs__assess_string/cs__assess_string.c +1 -1
- data/ext/cs__assess_string/extconf.rb +1 -1
- data/ext/cs__assess_string_interpolation26/cs__assess_string_interpolation26.c +1 -1
- data/ext/cs__assess_string_interpolation26/extconf.rb +1 -1
- data/ext/cs__assess_yield_track/cs__assess_yield_track.c +1 -1
- data/ext/cs__assess_yield_track/extconf.rb +1 -1
- data/ext/cs__common/cs__common.c +5 -5
- data/ext/cs__common/cs__common.h +4 -4
- data/ext/cs__common/extconf.rb +1 -1
- data/ext/cs__contrast_patch/cs__contrast_patch.c +22 -25
- data/ext/cs__contrast_patch/extconf.rb +1 -1
- data/ext/cs__protect_kernel/cs__protect_kernel.c +1 -1
- data/ext/cs__protect_kernel/extconf.rb +1 -1
- data/ext/extconf_common.rb +2 -6
- data/lib/contrast-agent.rb +1 -1
- data/lib/contrast.rb +20 -1
- data/lib/contrast/agent.rb +6 -4
- data/lib/contrast/agent/assess.rb +2 -11
- data/lib/contrast/agent/assess/contrast_event.rb +54 -71
- data/lib/contrast/agent/assess/contrast_object.rb +7 -4
- data/lib/contrast/agent/assess/events/event_factory.rb +3 -2
- data/lib/contrast/agent/assess/events/source_event.rb +7 -2
- data/lib/contrast/agent/assess/finalizers/freeze.rb +1 -1
- data/lib/contrast/agent/assess/finalizers/hash.rb +33 -34
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +34 -16
- data/lib/contrast/agent/assess/policy/patcher.rb +11 -18
- data/lib/contrast/agent/assess/policy/policy.rb +1 -1
- data/lib/contrast/agent/assess/policy/policy_node.rb +26 -34
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
- data/lib/contrast/agent/assess/policy/preshift.rb +4 -2
- data/lib/contrast/agent/assess/policy/propagation_method.rb +32 -30
- data/lib/contrast/agent/assess/policy/propagation_node.rb +20 -9
- data/lib/contrast/agent/assess/policy/propagator.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/append.rb +29 -14
- data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/center.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +22 -17
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +4 -2
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +23 -19
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/select.rb +3 -13
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +24 -14
- data/lib/contrast/agent/assess/policy/propagator/split.rb +18 -15
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +32 -22
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +64 -45
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +7 -4
- data/lib/contrast/agent/assess/policy/source_method.rb +92 -81
- data/lib/contrast/agent/assess/policy/source_node.rb +1 -1
- data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +8 -6
- data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +2 -4
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -3
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +7 -8
- data/lib/contrast/agent/assess/policy/trigger_method.rb +109 -76
- data/lib/contrast/agent/assess/policy/trigger_node.rb +33 -11
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +60 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +3 -5
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +7 -5
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +4 -13
- data/lib/contrast/agent/assess/properties.rb +1 -3
- data/lib/contrast/agent/assess/property/evented.rb +9 -6
- data/lib/contrast/agent/assess/property/tagged.rb +38 -20
- data/lib/contrast/agent/assess/property/updated.rb +1 -1
- data/lib/contrast/agent/assess/rule/provider.rb +1 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +12 -6
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +5 -2
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +4 -6
- data/lib/contrast/agent/assess/tag.rb +1 -1
- data/lib/contrast/agent/assess/tracker.rb +2 -2
- data/lib/contrast/agent/at_exit_hook.rb +1 -1
- data/lib/contrast/agent/class_reopener.rb +4 -2
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +1 -1
- data/lib/contrast/agent/deadzone/policy/policy.rb +7 -3
- data/lib/contrast/agent/disable_reaction.rb +2 -4
- data/lib/contrast/agent/exclusion_matcher.rb +6 -12
- data/lib/contrast/agent/inventory.rb +1 -2
- data/lib/contrast/agent/inventory/dependencies.rb +3 -1
- data/lib/contrast/agent/inventory/dependency_analysis.rb +1 -1
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +35 -23
- data/lib/contrast/agent/inventory/policy/datastores.rb +1 -1
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/inventory/policy/trigger_node.rb +1 -1
- data/lib/contrast/agent/middleware.rb +111 -110
- data/lib/contrast/agent/module_data.rb +4 -4
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +1 -1
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +9 -4
- data/lib/contrast/agent/patching/policy/method_policy.rb +7 -3
- data/lib/contrast/agent/patching/policy/module_policy.rb +15 -8
- data/lib/contrast/agent/patching/policy/patch.rb +23 -29
- data/lib/contrast/agent/patching/policy/patch_status.rb +8 -9
- data/lib/contrast/agent/patching/policy/patcher.rb +72 -64
- data/lib/contrast/agent/patching/policy/policy.rb +14 -21
- data/lib/contrast/agent/patching/policy/policy_node.rb +15 -5
- data/lib/contrast/agent/patching/policy/trigger_node.rb +26 -10
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +3 -4
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +2 -2
- data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +6 -10
- data/lib/contrast/agent/protect/policy/policy.rb +1 -1
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +6 -6
- data/lib/contrast/agent/protect/policy/trigger_node.rb +1 -1
- data/lib/contrast/agent/protect/rule.rb +1 -1
- data/lib/contrast/agent/protect/rule/base.rb +19 -33
- data/lib/contrast/agent/protect/rule/base_service.rb +10 -6
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +15 -19
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +7 -14
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +4 -15
- data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -3
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +2 -4
- data/lib/contrast/agent/protect/rule/path_traversal.rb +6 -6
- data/lib/contrast/agent/protect/rule/sqli.rb +19 -13
- data/lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb +2 -2
- data/lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +2 -2
- data/lib/contrast/agent/protect/rule/xss.rb +2 -2
- data/lib/contrast/agent/protect/rule/xxe.rb +6 -13
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +2 -3
- data/lib/contrast/agent/railtie.rb +1 -1
- data/lib/contrast/agent/reaction_processor.rb +12 -11
- data/lib/contrast/agent/request.rb +25 -24
- data/lib/contrast/agent/request_context.rb +25 -23
- data/lib/contrast/agent/request_handler.rb +1 -1
- data/lib/contrast/agent/response.rb +1 -1
- data/lib/contrast/agent/rewriter.rb +6 -4
- data/lib/contrast/agent/rule_set.rb +3 -3
- data/lib/contrast/agent/scope.rb +1 -1
- data/lib/contrast/agent/service_heartbeat.rb +3 -4
- data/lib/contrast/agent/static_analysis.rb +1 -1
- data/lib/contrast/agent/thread.rb +2 -2
- data/lib/contrast/agent/thread_watcher.rb +21 -6
- data/lib/contrast/agent/tracepoint_hook.rb +2 -2
- data/lib/contrast/agent/version.rb +2 -2
- data/lib/contrast/agent/worker_thread.rb +1 -1
- data/lib/contrast/api.rb +1 -1
- data/lib/contrast/api/communication.rb +1 -1
- data/lib/contrast/api/communication/connection_status.rb +1 -1
- data/lib/contrast/api/communication/messaging_queue.rb +19 -22
- data/lib/contrast/api/communication/response_processor.rb +13 -8
- data/lib/contrast/api/communication/service_lifecycle.rb +5 -3
- data/lib/contrast/api/communication/socket.rb +1 -1
- data/lib/contrast/api/communication/socket_client.rb +30 -35
- data/lib/contrast/api/communication/speedracer.rb +6 -10
- data/lib/contrast/api/communication/tcp_socket.rb +1 -1
- data/lib/contrast/api/communication/unix_socket.rb +1 -1
- data/lib/contrast/api/decorators.rb +3 -1
- data/lib/contrast/api/decorators/address.rb +1 -1
- data/lib/contrast/api/decorators/agent_startup.rb +58 -0
- data/lib/contrast/api/decorators/application_settings.rb +1 -1
- data/lib/contrast/api/decorators/application_startup.rb +57 -0
- data/lib/contrast/api/decorators/application_update.rb +1 -1
- data/lib/contrast/api/decorators/http_request.rb +1 -1
- data/lib/contrast/api/decorators/input_analysis.rb +1 -1
- data/lib/contrast/api/decorators/instrumentation_mode.rb +37 -0
- data/lib/contrast/api/decorators/library.rb +9 -7
- data/lib/contrast/api/decorators/library_usage_update.rb +1 -1
- data/lib/contrast/api/decorators/message.rb +4 -4
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +1 -1
- data/lib/contrast/api/decorators/route_coverage.rb +16 -6
- data/lib/contrast/api/decorators/server_features.rb +1 -1
- data/lib/contrast/api/decorators/trace_event.rb +46 -16
- data/lib/contrast/api/decorators/trace_event_object.rb +2 -4
- data/lib/contrast/api/decorators/trace_event_signature.rb +1 -1
- data/lib/contrast/api/decorators/trace_taint_range.rb +1 -1
- data/lib/contrast/api/decorators/trace_taint_range_tags.rb +2 -7
- data/lib/contrast/api/decorators/user_input.rb +1 -1
- data/lib/contrast/components/agent.rb +16 -15
- data/lib/contrast/components/app_context.rb +11 -29
- data/lib/contrast/components/assess.rb +6 -11
- data/lib/contrast/components/config.rb +3 -2
- data/lib/contrast/components/contrast_service.rb +8 -9
- data/lib/contrast/components/heap_dump.rb +1 -1
- data/lib/contrast/components/interface.rb +4 -3
- data/lib/contrast/components/inventory.rb +1 -1
- data/lib/contrast/components/logger.rb +1 -1
- data/lib/contrast/components/protect.rb +11 -14
- data/lib/contrast/components/sampling.rb +55 -7
- data/lib/contrast/components/scope.rb +2 -1
- data/lib/contrast/components/settings.rb +29 -99
- data/lib/contrast/config.rb +1 -1
- data/lib/contrast/config/agent_configuration.rb +1 -1
- data/lib/contrast/config/application_configuration.rb +1 -1
- data/lib/contrast/config/assess_configuration.rb +1 -1
- data/lib/contrast/config/assess_rules_configuration.rb +2 -4
- data/lib/contrast/config/base_configuration.rb +5 -6
- data/lib/contrast/config/default_value.rb +1 -1
- data/lib/contrast/config/exception_configuration.rb +2 -6
- data/lib/contrast/config/heap_dump_configuration.rb +13 -7
- data/lib/contrast/config/inventory_configuration.rb +1 -1
- data/lib/contrast/config/logger_configuration.rb +2 -6
- data/lib/contrast/config/protect_configuration.rb +1 -1
- data/lib/contrast/config/protect_rule_configuration.rb +23 -1
- data/lib/contrast/config/protect_rules_configuration.rb +1 -1
- data/lib/contrast/config/root_configuration.rb +1 -1
- data/lib/contrast/config/ruby_configuration.rb +1 -1
- data/lib/contrast/config/sampling_configuration.rb +1 -1
- data/lib/contrast/config/server_configuration.rb +1 -1
- data/lib/contrast/config/service_configuration.rb +1 -1
- data/lib/contrast/configuration.rb +4 -15
- data/lib/contrast/delegators/input_analysis.rb +12 -0
- data/lib/contrast/extension/assess.rb +1 -1
- data/lib/contrast/extension/assess/array.rb +2 -7
- data/lib/contrast/extension/assess/erb.rb +2 -8
- data/lib/contrast/extension/assess/eval_trigger.rb +3 -11
- data/lib/contrast/extension/assess/exec_trigger.rb +4 -14
- data/lib/contrast/extension/assess/fiber.rb +3 -13
- data/lib/contrast/extension/assess/hash.rb +1 -1
- data/lib/contrast/extension/assess/kernel.rb +3 -10
- data/lib/contrast/extension/assess/marshal.rb +3 -11
- data/lib/contrast/extension/assess/regexp.rb +2 -7
- data/lib/contrast/extension/assess/string.rb +4 -2
- data/lib/contrast/extension/delegator.rb +1 -1
- data/lib/contrast/extension/inventory.rb +1 -1
- data/lib/contrast/extension/kernel.rb +5 -3
- data/lib/contrast/extension/module.rb +1 -1
- data/lib/contrast/extension/protect.rb +1 -1
- data/lib/contrast/extension/protect/kernel.rb +1 -1
- data/lib/contrast/extension/protect/psych.rb +1 -1
- data/lib/contrast/extension/thread.rb +1 -1
- data/lib/contrast/framework/base_support.rb +1 -1
- data/lib/contrast/framework/manager.rb +14 -17
- data/lib/contrast/framework/platform_version.rb +1 -1
- data/lib/contrast/framework/rack/patch/session_cookie.rb +6 -19
- data/lib/contrast/framework/rack/patch/support.rb +7 -5
- data/lib/contrast/framework/rack/support.rb +1 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -1
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +8 -3
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +4 -4
- data/lib/contrast/framework/rails/patch/support.rb +5 -3
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +5 -2
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +3 -1
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +3 -1
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +3 -1
- data/lib/contrast/framework/rails/support.rb +45 -46
- data/lib/contrast/framework/sinatra/support.rb +103 -42
- data/lib/contrast/funchook/funchook.rb +2 -6
- data/lib/contrast/logger/application.rb +13 -10
- data/lib/contrast/logger/format.rb +3 -6
- data/lib/contrast/logger/log.rb +36 -19
- data/lib/contrast/logger/request.rb +2 -3
- data/lib/contrast/logger/time.rb +1 -1
- data/lib/contrast/security_exception.rb +2 -2
- data/lib/contrast/tasks/config.rb +1 -1
- data/lib/contrast/tasks/service.rb +6 -2
- data/lib/contrast/utils/assess/sampling_util.rb +1 -1
- data/lib/contrast/utils/assess/tracking_util.rb +2 -3
- data/lib/contrast/utils/class_util.rb +18 -12
- data/lib/contrast/utils/duck_utils.rb +1 -1
- data/lib/contrast/utils/env_configuration_item.rb +1 -1
- data/lib/contrast/utils/hash_digest.rb +16 -24
- data/lib/contrast/utils/heap_dump_util.rb +104 -88
- data/lib/contrast/utils/invalid_configuration_util.rb +22 -13
- data/lib/contrast/utils/inventory_util.rb +1 -1
- data/lib/contrast/utils/io_util.rb +2 -2
- data/lib/contrast/utils/job_servers_running.rb +10 -5
- data/lib/contrast/utils/object_share.rb +1 -1
- data/lib/contrast/utils/os.rb +3 -2
- data/lib/contrast/utils/preflight_util.rb +1 -1
- data/lib/contrast/utils/resource_loader.rb +1 -1
- data/lib/contrast/utils/ruby_ast_rewriter.rb +3 -2
- data/lib/contrast/utils/sha256_builder.rb +1 -1
- data/lib/contrast/utils/stack_trace_utils.rb +1 -1
- data/lib/contrast/utils/string_utils.rb +1 -1
- data/lib/contrast/utils/tag_util.rb +1 -1
- data/lib/contrast/utils/thread_tracker.rb +1 -1
- data/lib/contrast/utils/timer.rb +1 -1
- data/resources/assess/policy.json +8 -11
- data/resources/deadzone/policy.json +7 -17
- data/ruby-agent.gemspec +66 -27
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- data/sonar-project.properties +9 -0
- metadata +154 -156
- data/lib/contrast/agent/assess/rule.rb +0 -18
- data/lib/contrast/agent/assess/rule/base.rb +0 -52
- data/lib/contrast/agent/assess/rule/redos.rb +0 -67
- data/lib/contrast/agent/inventory/gemfile_digest_cache.rb +0 -38
- data/lib/contrast/common_agent_configuration.rb +0 -87
- data/lib/contrast/framework/sinatra/patch/base.rb +0 -83
- data/lib/contrast/framework/sinatra/patch/support.rb +0 -27
- data/lib/contrast/utils/prevent_serialization.rb +0 -52
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/agent/patching/policy/method_policy'
|
|
@@ -27,6 +27,9 @@ module Contrast
|
|
|
27
27
|
class_name = klass.cs__name
|
|
28
28
|
instance_methods = klass.instance_methods
|
|
29
29
|
instance_methods.concat(klass.private_instance_methods)
|
|
30
|
+
current_context = Contrast::Agent::REQUEST_TRACKER.current
|
|
31
|
+
current_request = current_context&.request
|
|
32
|
+
|
|
30
33
|
tainted_columns.each_pair do |field, properties|
|
|
31
34
|
next unless properties
|
|
32
35
|
|
|
@@ -34,14 +37,14 @@ module Contrast
|
|
|
34
37
|
# Move on if we already know about this Dynamic Source
|
|
35
38
|
next if Contrast::Agent::Assess::Policy::Policy.instance.find_source_node(class_name, method_name, true)
|
|
36
39
|
|
|
37
|
-
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)
|
|
38
42
|
Contrast::Agent::Assess::Policy::Policy.instance.add_node(dynamic_source_node, :dynamic_source)
|
|
39
43
|
method_policy = build_source_policy(method_name, dynamic_source_node)
|
|
40
44
|
Contrast::Agent::Patching::Policy::Patcher.patch_method(klass, instance_methods, method_policy)
|
|
41
|
-
current_context = Contrast::Agent::REQUEST_TRACKER.current
|
|
42
45
|
next unless current_context
|
|
43
46
|
|
|
44
|
-
dynamic_source = create_dynamic_source(
|
|
47
|
+
dynamic_source = create_dynamic_source(current_request, dynamic_source_node, field, properties)
|
|
45
48
|
node_id = Contrast::Utils::StringUtils.force_utf8(dynamic_source_node.id)
|
|
46
49
|
current_context.activity.dynamic_sources[node_id] = dynamic_source
|
|
47
50
|
end
|
|
@@ -56,8 +59,10 @@ module Contrast
|
|
|
56
59
|
# @param class_name [String] the name of the Class to patch
|
|
57
60
|
# @param method_name [Symbol] the name of the Method to patch
|
|
58
61
|
# @param tags [Set<String>] the tags this event should apply
|
|
62
|
+
# @param request [Contrast::Agent::Request] the request during
|
|
63
|
+
# which this source is to be created.
|
|
59
64
|
# @return [Contrast::Agent::Assess::Policy::SourceNode]
|
|
60
|
-
def create_source_node class_name, method_name, tags
|
|
65
|
+
def create_source_node class_name, method_name, tags, request
|
|
61
66
|
node = Contrast::Agent::Assess::Policy::SourceNode.new
|
|
62
67
|
node.class_name = class_name
|
|
63
68
|
node.instance_method = true
|
|
@@ -72,8 +77,7 @@ module Contrast
|
|
|
72
77
|
node.add_property(READ_TABLE, class_name)
|
|
73
78
|
node.add_property(READ_COLUMN, method_name)
|
|
74
79
|
node.add_property(WRITE_QUERY_TIME, Contrast::Utils::Timer.now_ms)
|
|
75
|
-
|
|
76
|
-
node.add_property(WRITE_QUERY_URL, url)
|
|
80
|
+
node.add_property(WRITE_QUERY_URL, request&.normalized_uri)
|
|
77
81
|
node
|
|
78
82
|
end
|
|
79
83
|
|
|
@@ -92,8 +96,8 @@ module Contrast
|
|
|
92
96
|
method_policy
|
|
93
97
|
end
|
|
94
98
|
|
|
95
|
-
# @param
|
|
96
|
-
#
|
|
99
|
+
# @param request [Contrast::Agent::Request] the request during
|
|
100
|
+
# which this source is to be created.
|
|
97
101
|
# @param source_node [Contrast::Agent::Assess::Policy::SourceNode]
|
|
98
102
|
# the SourceNode that applies to this method
|
|
99
103
|
# @param field [String] the name of the method to which this source
|
|
@@ -104,22 +108,36 @@ module Contrast
|
|
|
104
108
|
# @return [Contrast::Api::Dtm::DynamicSource] the message to send
|
|
105
109
|
# to the Service to allow it to report the events leading up to
|
|
106
110
|
# the creation of the Dynamic Source
|
|
107
|
-
def create_dynamic_source
|
|
111
|
+
def create_dynamic_source request, source_node, field, properties
|
|
108
112
|
dynamic_source = Contrast::Api::Dtm::DynamicSource.new
|
|
109
113
|
dynamic_source.class_name = Contrast::Utils::StringUtils.force_utf8(source_node.class_name)
|
|
110
114
|
dynamic_source.method_name = Contrast::Utils::StringUtils.force_utf8(field)
|
|
111
115
|
dynamic_source.instance_method = source_node.instance_method?
|
|
112
116
|
dynamic_source.target = Contrast::Utils::StringUtils.force_utf8(source_node.target_string)
|
|
117
|
+
append_properties!(dynamic_source, request, source_node, field)
|
|
118
|
+
append_events!(dynamic_source, properties.event)
|
|
119
|
+
dynamic_source
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Append the properties needed to reconstruct the given DynamicSource in other dataflows and for rendering
|
|
123
|
+
# in TeamServer
|
|
124
|
+
#
|
|
125
|
+
# @param dynamic_source [Contrast::Api::Dtm::DynamicSource] the message to send to the Service to allow it
|
|
126
|
+
# to report the events leading up to the creation of the Dynamic Source.
|
|
127
|
+
# @param request [Contrast::Agent::Request] the request during which this source is to be created.
|
|
128
|
+
# @param source_node [Contrast::Agent::Assess::Policy::SourceNode] the SourceNode that applies to this
|
|
129
|
+
# method.
|
|
130
|
+
# @param field [String] the name of the method to which this source applies.
|
|
131
|
+
def append_properties! dynamic_source, request, source_node, field
|
|
113
132
|
dynamic_source.properties[READ_TABLE] = Contrast::Utils::StringUtils.force_utf8(source_node.class_name)
|
|
114
133
|
dynamic_source.properties[READ_COLUMN] = Contrast::Utils::StringUtils.force_utf8(field)
|
|
115
|
-
dynamic_source.properties[WRITE_QUERY_TIME] =
|
|
116
|
-
|
|
117
|
-
dynamic_source.properties[WRITE_QUERY_URL] =
|
|
118
|
-
|
|
119
|
-
dynamic_source
|
|
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)
|
|
120
138
|
end
|
|
121
139
|
|
|
122
|
-
def append_events dynamic_source, event
|
|
140
|
+
def append_events! dynamic_source, event
|
|
123
141
|
return unless event
|
|
124
142
|
|
|
125
143
|
event.parent_events&.each do |parent_event|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/agent/assess/policy/policy'
|
|
@@ -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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'json'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/agent/patching/policy/policy_node'
|
|
@@ -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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/components/interface'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/components/interface'
|
|
@@ -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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'set'
|
|
@@ -86,10 +86,6 @@ module Contrast
|
|
|
86
86
|
SPLIT_ACTION => Contrast::Agent::Assess::Policy::Propagator::Split
|
|
87
87
|
}.cs__freeze
|
|
88
88
|
|
|
89
|
-
def context_available?
|
|
90
|
-
!!Contrast::Agent::REQUEST_TRACKER.current
|
|
91
|
-
end
|
|
92
|
-
|
|
93
89
|
# I lied above. We had to figure out what the target of the
|
|
94
90
|
# propagation was. Now that we know, we'll actually do things to
|
|
95
91
|
# it. Note that the return of this method will replace the original
|
|
@@ -144,13 +140,7 @@ module Contrast
|
|
|
144
140
|
!!target
|
|
145
141
|
end
|
|
146
142
|
|
|
147
|
-
ZERO_LENGTH_ACTIONS = [
|
|
148
|
-
DB_WRITE_ACTION,
|
|
149
|
-
CUSTOM_ACTION,
|
|
150
|
-
KEEP_ACTION,
|
|
151
|
-
REPLACE_ACTION,
|
|
152
|
-
SPLAT_ACTION
|
|
153
|
-
].cs__freeze
|
|
143
|
+
ZERO_LENGTH_ACTIONS = [DB_WRITE_ACTION, CUSTOM_ACTION, KEEP_ACTION, REPLACE_ACTION, SPLAT_ACTION].cs__freeze
|
|
154
144
|
# If the action required needs a length and the target does not have
|
|
155
145
|
# one, the length is not valid
|
|
156
146
|
def valid_length? target, action
|
|
@@ -225,7 +215,7 @@ module Contrast
|
|
|
225
215
|
|
|
226
216
|
# This is checked right before actual propagation
|
|
227
217
|
def propagation_possible? propagation_node, target
|
|
228
|
-
return false unless
|
|
218
|
+
return false unless propagation_node && valid_target?(target, propagation_node)
|
|
229
219
|
return false unless valid_length?(target, propagation_node.action)
|
|
230
220
|
|
|
231
221
|
true
|
|
@@ -249,7 +239,7 @@ module Contrast
|
|
|
249
239
|
|
|
250
240
|
def handle_enumerable_propagation propagation_node, preshift, target, object, ret, args, block
|
|
251
241
|
target.each do |value|
|
|
252
|
-
next if target == value
|
|
242
|
+
next if target == value
|
|
253
243
|
|
|
254
244
|
apply_propagator(propagation_node, preshift, value, object, ret, args, block)
|
|
255
245
|
end
|
|
@@ -258,22 +248,12 @@ module Contrast
|
|
|
258
248
|
def handle_cs_properties_propagation propagation_node, preshift, target, object, ret, args, _block
|
|
259
249
|
return if propagation_node.action == NOOP_ACTION
|
|
260
250
|
return unless can_propagate?(propagation_node, preshift, target)
|
|
251
|
+
return unless (propagation_class = find_propagation_class(propagation_node))
|
|
261
252
|
|
|
262
|
-
propagation_class = PROPAGATION_ACTIONS.fetch(propagation_node.action, nil)
|
|
263
|
-
unless propagation_class
|
|
264
|
-
logger.warn(
|
|
265
|
-
'Unknown propagation action received. Unable to propagate.',
|
|
266
|
-
node_id: propagation_node.id,
|
|
267
|
-
action: propagation_node.action)
|
|
268
|
-
return
|
|
269
|
-
end
|
|
270
253
|
restore_frozen_state = false
|
|
271
254
|
if target.cs__frozen? && !Contrast::Agent::Assess::Tracker.trackable?(target)
|
|
272
|
-
return unless
|
|
273
|
-
return unless
|
|
274
|
-
|
|
275
|
-
dup = safe_dup(ret)
|
|
276
|
-
return unless dup
|
|
255
|
+
return unless can_handle_frozen?(propagation_node)
|
|
256
|
+
return unless (dup = safe_dup(ret))
|
|
277
257
|
|
|
278
258
|
restore_frozen_state = true
|
|
279
259
|
ret = dup
|
|
@@ -297,11 +277,33 @@ module Contrast
|
|
|
297
277
|
|
|
298
278
|
properties.add_properties(propagation_node.properties)
|
|
299
279
|
properties.build_event(propagation_node, target, object, ret, args)
|
|
300
|
-
logger.trace('Propagation detected',
|
|
301
|
-
node_id: propagation_node.id,
|
|
302
|
-
target_id: target.__id__)
|
|
280
|
+
logger.trace('Propagation detected', node_id: propagation_node.id, target_id: target.__id__)
|
|
303
281
|
restore_frozen_state ? ret : nil
|
|
304
282
|
end
|
|
283
|
+
|
|
284
|
+
# Find the propagation class from the given node, if one exists.
|
|
285
|
+
#
|
|
286
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs a
|
|
287
|
+
# propagation event.
|
|
288
|
+
# @return [Contrast::Agent::Assess::Policy::Propagator, nil]
|
|
289
|
+
def find_propagation_class propagation_node
|
|
290
|
+
unless (propagation_class = PROPAGATION_ACTIONS.fetch(propagation_node.action, nil))
|
|
291
|
+
logger.warn('Unknown propagation action received. Unable to propagate.',
|
|
292
|
+
node_id: propagation_node.id,
|
|
293
|
+
action: propagation_node.action)
|
|
294
|
+
end
|
|
295
|
+
propagation_class
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# We can handle frozen propagation iff we're allowed to, as determined by configuration, and the target of
|
|
299
|
+
# the propagation is a return, as that's a replaceable value.
|
|
300
|
+
#
|
|
301
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs a
|
|
302
|
+
# propagation event.
|
|
303
|
+
# @return [Boolean]
|
|
304
|
+
def can_handle_frozen? propagation_node
|
|
305
|
+
ASSESS.track_frozen_sources? && propagation_node.targets[0] == Contrast::Utils::ObjectShare::RETURN_KEY
|
|
306
|
+
end
|
|
305
307
|
end
|
|
306
308
|
end
|
|
307
309
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/agent/assess/policy/policy_node'
|
|
@@ -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
|