contrast-agent 3.8.5 → 3.9.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/ext/cs__assess_array/cs__assess_array.c +1 -1
- data/ext/cs__assess_module/cs__assess_module.c +0 -1
- data/ext/cs__assess_yield_track/cs__assess_yield_track.c +34 -0
- data/ext/cs__assess_yield_track/cs__assess_yield_track.h +12 -0
- data/ext/{cs__scope → cs__assess_yield_track}/extconf.rb +0 -0
- data/ext/cs__common/cs__common.c +6 -6
- data/ext/cs__common/cs__common.h +3 -1
- data/ext/cs__contrast_patch/cs__contrast_patch.c +142 -119
- data/ext/cs__contrast_patch/cs__contrast_patch.h +3 -0
- data/funchook/autom4te.cache/requests +48 -48
- data/funchook/config.log +2 -2
- data/lib/contrast/agent.rb +15 -5
- data/lib/contrast/agent/assess.rb +0 -1
- data/lib/contrast/agent/assess/contrast_event.rb +9 -8
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +68 -18
- data/lib/contrast/agent/assess/policy/policy.rb +0 -14
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
- data/lib/contrast/agent/assess/policy/preshift.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagation_method.rb +4 -2
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -2
- data/lib/contrast/agent/assess/policy/propagator/split.rb +166 -1
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +1 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +199 -140
- data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +30 -0
- data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +36 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +238 -153
- data/lib/contrast/agent/assess/policy/trigger_node.rb +54 -9
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +13 -0
- data/lib/contrast/agent/assess/properties.rb +29 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +35 -31
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +1 -1
- data/lib/contrast/agent/class_reopener.rb +98 -55
- data/lib/contrast/agent/feature_state.rb +1 -1
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/logger_manager.rb +2 -2
- data/lib/contrast/agent/middleware.rb +1 -3
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +40 -4
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +33 -8
- data/lib/contrast/agent/patching/policy/method_policy.rb +20 -7
- data/lib/contrast/agent/patching/policy/patch.rb +54 -23
- data/lib/contrast/agent/patching/policy/patch_status.rb +0 -2
- data/lib/contrast/agent/patching/policy/patcher.rb +10 -11
- data/lib/contrast/agent/patching/policy/policy.rb +4 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +14 -1
- data/lib/contrast/agent/patching/policy/trigger_node.rb +2 -1
- data/lib/contrast/agent/protect/policy/policy.rb +6 -6
- data/lib/contrast/agent/protect/rule/base.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +3 -25
- data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
- data/lib/contrast/agent/railtie.rb +11 -5
- data/lib/contrast/agent/request.rb +1 -19
- data/lib/contrast/agent/request_context.rb +1 -1
- data/lib/contrast/agent/rewriter.rb +4 -3
- data/lib/contrast/agent/scope.rb +116 -19
- data/lib/contrast/agent/service_heartbeat.rb +5 -2
- data/lib/contrast/agent/settings_state.rb +12 -8
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api.rb +1 -0
- data/lib/contrast/api/speedracer.rb +2 -2
- data/lib/contrast/components/agent.rb +26 -7
- data/lib/contrast/components/app_context.rb +8 -45
- data/lib/contrast/components/contrast_service.rb +3 -4
- data/lib/contrast/components/interface.rb +1 -1
- data/lib/contrast/components/scope.rb +56 -26
- data/lib/contrast/config/ruby_configuration.rb +8 -3
- data/lib/contrast/delegators.rb +9 -0
- data/lib/contrast/delegators/application_update.rb +32 -0
- data/lib/contrast/extensions/framework/rack/cookie.rb +24 -0
- data/lib/contrast/extensions/framework/rack/request.rb +24 -0
- data/lib/contrast/extensions/framework/rack/response.rb +23 -0
- data/lib/contrast/extensions/framework/rails/action_controller_railties_helper_inherited.rb +20 -0
- data/lib/contrast/extensions/framework/rails/active_record.rb +26 -0
- data/lib/contrast/extensions/framework/rails/active_record_named.rb +53 -0
- data/lib/contrast/extensions/framework/rails/active_record_time_zone_inherited.rb +21 -0
- data/lib/contrast/extensions/framework/rails/buffer.rb +28 -0
- data/lib/contrast/extensions/framework/rails/configuration.rb +27 -0
- data/lib/contrast/extensions/framework/sinatra/base.rb +59 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess.rb +12 -11
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/array.rb +4 -3
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/assess_extension.rb +0 -2
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/basic_object.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/erb.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/exec_trigger.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/fiber.rb +3 -4
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/hash.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/kernel.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/module.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/regexp.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/string.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/tilt_template_trigger.rb +0 -0
- data/lib/contrast/extensions/ruby_core/assess/xpath_library_trigger.rb +40 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/delegator.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/eval_trigger.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/inventory.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/inventory/datastores.rb +1 -1
- data/lib/contrast/extensions/ruby_core/module.rb +17 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_command_injection_rule.rb +8 -6
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_deserialization_rule.rb +7 -5
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_no_sqli_rule.rb +5 -3
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_path_traversal_rule.rb +31 -27
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_sqli_rule.rb +5 -3
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_xxe_rule.rb +9 -7
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/kernel.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/psych.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/thread.rb +0 -0
- data/lib/contrast/framework/base_support.rb +63 -0
- data/lib/contrast/framework/manager.rb +109 -0
- data/lib/contrast/framework/platform_version.rb +21 -0
- data/lib/contrast/framework/rails_support.rb +88 -0
- data/lib/contrast/framework/sinatra_application_helper.rb +49 -0
- data/lib/contrast/framework/sinatra_support.rb +94 -0
- data/lib/contrast/framework/view_technologies_descriptor.rb +20 -0
- data/lib/contrast/utils/assess/tracking_util.rb +2 -4
- data/lib/contrast/utils/class_util.rb +92 -37
- data/lib/contrast/utils/duck_utils.rb +59 -39
- data/lib/contrast/utils/environment_util.rb +5 -75
- data/lib/contrast/utils/freeze_util.rb +3 -7
- data/lib/contrast/utils/invalid_configuration_util.rb +5 -5
- data/lib/contrast/utils/job_servers_running.rb +39 -0
- data/lib/contrast/utils/ruby_ast_rewriter.rb +2 -2
- data/lib/contrast/utils/service_response_util.rb +0 -6
- data/lib/contrast/utils/sinatra_helper.rb +6 -0
- data/lib/contrast/utils/stack_trace_utils.rb +1 -1
- data/resources/assess/policy.json +74 -23
- data/resources/inventory/policy.json +1 -1
- data/resources/protect/policy.json +11 -9
- data/resources/rubocops/object/frozen_cop.rb +1 -1
- data/ruby-agent.gemspec +2 -0
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +94 -57
- data/ext/cs__scope/cs__scope.c +0 -96
- data/ext/cs__scope/cs__scope.h +0 -33
- data/lib/contrast/agent/assess/class_reverter.rb +0 -82
- data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +0 -28
- data/lib/contrast/core_extensions/module.rb +0 -42
- data/lib/contrast/core_extensions/object.rb +0 -27
- data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +0 -48
- data/lib/contrast/rails_extensions/assess/active_record.rb +0 -32
- data/lib/contrast/rails_extensions/assess/active_record_named.rb +0 -61
- data/lib/contrast/rails_extensions/assess/configuration.rb +0 -26
- data/lib/contrast/rails_extensions/buffer.rb +0 -30
- data/lib/contrast/rails_extensions/rack.rb +0 -45
- data/lib/contrast/sinatra_extensions/assess/cookie.rb +0 -26
- data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +0 -59
- data/lib/contrast/utils/operating_environment.rb +0 -38
- data/lib/contrast/utils/path_util.rb +0 -151
- data/lib/contrast/utils/scope_util.rb +0 -99
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
cs__scoped_require 'contrast/agent/settings_state'
|
|
5
|
-
cs__scoped_require 'contrast/
|
|
5
|
+
cs__scoped_require 'contrast/extensions/ruby_core/module'
|
|
6
6
|
cs__scoped_require 'contrast/utils/boolean_util'
|
|
7
7
|
|
|
8
8
|
module Contrast
|
|
@@ -5,7 +5,7 @@ cs__scoped_require 'contrast/agent/inventory/policy/trigger_node'
|
|
|
5
5
|
cs__scoped_require 'contrast/agent/patching/policy/policy'
|
|
6
6
|
|
|
7
7
|
# classes required by patches in the policy
|
|
8
|
-
cs__scoped_require 'contrast/
|
|
8
|
+
cs__scoped_require 'contrast/extensions/ruby_core/inventory/datastores'
|
|
9
9
|
|
|
10
10
|
module Contrast
|
|
11
11
|
module Agent
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
cs__scoped_require 'logger'
|
|
5
5
|
|
|
6
|
-
cs__scoped_require 'contrast/
|
|
6
|
+
cs__scoped_require 'contrast/extensions/ruby_core/module'
|
|
7
7
|
cs__scoped_require 'contrast/components/interface'
|
|
8
8
|
|
|
9
9
|
module Contrast
|
|
@@ -60,7 +60,7 @@ module Contrast
|
|
|
60
60
|
private
|
|
61
61
|
|
|
62
62
|
def default_progname
|
|
63
|
-
|
|
63
|
+
'Contrast Agent'
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def build path: STDOUT_STR, progname: default_progname, level_const: DEFAULT_LEVEL
|
|
@@ -4,16 +4,14 @@
|
|
|
4
4
|
cs__scoped_require 'ipaddr'
|
|
5
5
|
cs__scoped_require 'json'
|
|
6
6
|
cs__scoped_require 'rack'
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
cs__scoped_require 'contrast/security_exception'
|
|
9
9
|
cs__scoped_require 'contrast/utils/object_share'
|
|
10
10
|
cs__scoped_require 'contrast/utils/gemfile_reader'
|
|
11
|
-
cs__scoped_require 'contrast/utils/operating_environment'
|
|
12
11
|
cs__scoped_require 'contrast/agent/service_heartbeat'
|
|
13
12
|
cs__scoped_require 'contrast/components/interface'
|
|
14
13
|
cs__scoped_require 'contrast/utils/heap_dump_util'
|
|
15
14
|
|
|
16
|
-
cs__scoped_require 'contrast/utils/path_util'
|
|
17
15
|
cs__scoped_require 'contrast/utils/timer'
|
|
18
16
|
cs__scoped_require 'contrast/utils/freeze_util'
|
|
19
17
|
cs__scoped_require 'contrast/utils/service_sender_util'
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
cs__scoped_require 'contrast/utils/class_util'
|
|
5
|
+
|
|
4
6
|
module Contrast
|
|
5
7
|
module Agent
|
|
6
8
|
module Patching
|
|
7
9
|
module Policy
|
|
8
10
|
# Used to handle tracking patches that need to apply special instrumentation when a module is loaded
|
|
9
11
|
class AfterLoadPatch
|
|
10
|
-
attr_reader :applied, :module_name, :instrumentation_file_path
|
|
11
|
-
def initialize module_name, instrumentation_file_path
|
|
12
|
+
attr_reader :applied, :module_name, :instrumentation_file_path, :method_to_instrument
|
|
13
|
+
def initialize module_name, instrumentation_file_path, method_to_instrument: nil
|
|
12
14
|
@applied = false
|
|
13
15
|
@module_name = module_name
|
|
16
|
+
@method_to_instrument = method_to_instrument
|
|
14
17
|
@instrumentation_file_path = instrumentation_file_path
|
|
15
18
|
end
|
|
16
19
|
|
|
@@ -18,18 +21,51 @@ module Contrast
|
|
|
18
21
|
@applied
|
|
19
22
|
end
|
|
20
23
|
|
|
24
|
+
# Modules can be re-opened, so the first load may not
|
|
25
|
+
# necessarily define the method we're looking for:
|
|
26
|
+
#
|
|
27
|
+
# patching MyMod#instrumentable:
|
|
28
|
+
#
|
|
29
|
+
# file1:
|
|
30
|
+
# module MyMod
|
|
31
|
+
# def unrelated <-- false lead
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# file2:
|
|
36
|
+
# module MyMod
|
|
37
|
+
# def instrumentable <-- actual target
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
def blocked_by_method?
|
|
41
|
+
return true unless target_defined? # bc no methods are loaded
|
|
42
|
+
return false unless method_to_instrument
|
|
43
|
+
|
|
44
|
+
!module_lookup.instance_methods.include? method_to_instrument
|
|
45
|
+
end
|
|
46
|
+
|
|
21
47
|
def applies? loaded_module_name
|
|
22
|
-
loaded_module_name == module_name
|
|
48
|
+
(loaded_module_name == module_name) && !blocked_by_method?
|
|
23
49
|
end
|
|
24
50
|
|
|
25
51
|
def target_defined?
|
|
26
|
-
|
|
52
|
+
Contrast::Utils::ClassUtil.truly_defined?(module_name)
|
|
27
53
|
end
|
|
28
54
|
|
|
29
55
|
def instrument!
|
|
30
56
|
cs__scoped_require instrumentation_file_path
|
|
31
57
|
@applied = true
|
|
32
58
|
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def module_lookup
|
|
63
|
+
@_module_lookup ||= begin
|
|
64
|
+
Module.cs__const_get module_name
|
|
65
|
+
rescue StandardError => _e
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
33
69
|
end
|
|
34
70
|
end
|
|
35
71
|
end
|
|
@@ -12,18 +12,42 @@ module Contrast
|
|
|
12
12
|
# after they've been loaded
|
|
13
13
|
module AfterLoadPatcher
|
|
14
14
|
include Contrast::Components::Interface
|
|
15
|
-
access_component :logging
|
|
15
|
+
access_component :logging, :agent
|
|
16
16
|
|
|
17
17
|
AFTER_LOAD_PATCHES = Set.new([
|
|
18
18
|
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
19
19
|
'ActiveRecord::AttributeMethods::TimeZoneConversion::ClassMethods',
|
|
20
|
-
'contrast/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
'contrast/extensions/framework/rails/active_record_time_zone_inherited',
|
|
21
|
+
method_to_instrument: :inherited),
|
|
22
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
23
|
+
'ActionController::Railties::Helper::ClassMethods',
|
|
24
|
+
'contrast/extensions/framework/rails/action_controller_railties_helper_inherited',
|
|
25
|
+
method_to_instrument: :inherited),
|
|
26
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
27
|
+
'ActiveRecord::Scoping::Named::ClassMethods',
|
|
28
|
+
'contrast/extensions/framework/rails/active_record_named'),
|
|
29
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
30
|
+
'ActiveRecord::AttributeMethods::Read::ClassMethods',
|
|
31
|
+
'contrast/extensions/framework/rails/active_record'),
|
|
32
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
33
|
+
'Sinatra::Base',
|
|
34
|
+
'contrast/extensions/framework/sinatra/base'),
|
|
35
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
36
|
+
'Rails::Application::Configuration',
|
|
37
|
+
'contrast/extensions/framework/rails/configuration',
|
|
38
|
+
method_to_instrument: :session_store),
|
|
39
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
40
|
+
'Rack::Request',
|
|
41
|
+
'contrast/extensions/framework/rack/request'),
|
|
42
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
43
|
+
'Rack::Response',
|
|
44
|
+
'contrast/extensions/framework/rack/response'),
|
|
45
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
46
|
+
'ActionController::Live::Buffer',
|
|
47
|
+
'contrast/extensions/framework/rails/buffer'),
|
|
48
|
+
Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
|
|
49
|
+
'Rack::Session::Cookie',
|
|
50
|
+
'contrast/extensions/framework/rack/cookie')
|
|
27
51
|
])
|
|
28
52
|
|
|
29
53
|
# After initialization run a catchup check to instrument any already loaded modules we care about
|
|
@@ -31,6 +55,7 @@ module Contrast
|
|
|
31
55
|
applied = []
|
|
32
56
|
AFTER_LOAD_PATCHES.each do |after_load_patch|
|
|
33
57
|
next unless after_load_patch.target_defined?
|
|
58
|
+
next if AGENT.skip_instrumentation?(after_load_patch.module_name)
|
|
34
59
|
|
|
35
60
|
logger.debug("Detected loading of #{ after_load_patch.module_name } - applying instrumentation")
|
|
36
61
|
after_load_patch.instrument!
|
|
@@ -31,20 +31,33 @@ module Contrast
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def empty?
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
nodes.none?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def scopes_to_enter
|
|
38
|
+
@_scopes_to_enter ||= method_scopes
|
|
39
|
+
end
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
def scopes_to_exit
|
|
42
|
+
@_scopes_to_exit ||= method_scopes.reverse
|
|
42
43
|
end
|
|
43
44
|
|
|
44
45
|
def requires_custom_patch?
|
|
45
46
|
!!@trigger_node&.custom_patch?
|
|
46
47
|
end
|
|
47
48
|
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def nodes
|
|
52
|
+
@_nodes ||= [source_node, propagation_node, trigger_node, inventory_node, protect_node, deadzone_node].compact
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def method_scopes
|
|
56
|
+
# Implicitly, the scope precedence is the node order
|
|
57
|
+
# defined by #nodes.
|
|
58
|
+
@_method_scopes ||= nodes.flat_map(&:method_scope).tap(&:compact!).tap(&:uniq!)
|
|
59
|
+
end
|
|
60
|
+
|
|
48
61
|
class << self
|
|
49
62
|
# Given a Contrast::Agent::Patching::Policy::ModulePolicy, parse
|
|
50
63
|
# out its information for the given method in order to construct a
|
|
@@ -3,28 +3,27 @@
|
|
|
3
3
|
|
|
4
4
|
cs__scoped_require 'monitor'
|
|
5
5
|
# base
|
|
6
|
-
cs__scoped_require 'contrast/
|
|
6
|
+
cs__scoped_require 'contrast/extensions/ruby_core/module'
|
|
7
7
|
cs__scoped_require 'contrast/agent/patching/policy/method_policy'
|
|
8
8
|
cs__scoped_require 'contrast/agent/patching/policy/patch_status'
|
|
9
9
|
cs__scoped_require 'contrast/agent/patching/policy/trigger_node'
|
|
10
10
|
cs__scoped_require 'contrast/components/interface'
|
|
11
|
-
cs__scoped_require 'contrast/utils/scope_util'
|
|
12
11
|
|
|
13
12
|
# assess
|
|
14
13
|
cs__scoped_require 'contrast/agent/assess/policy/policy'
|
|
15
14
|
cs__scoped_require 'contrast/agent/assess/policy/propagation_method'
|
|
16
15
|
cs__scoped_require 'contrast/agent/assess/policy/source_method'
|
|
17
16
|
cs__scoped_require 'contrast/agent/assess/policy/trigger_method'
|
|
18
|
-
cs__scoped_require 'contrast/
|
|
17
|
+
cs__scoped_require 'contrast/extensions/ruby_core/assess'
|
|
19
18
|
|
|
20
19
|
# inventory
|
|
21
20
|
cs__scoped_require 'contrast/agent/inventory/policy/policy'
|
|
22
|
-
cs__scoped_require 'contrast/
|
|
21
|
+
cs__scoped_require 'contrast/extensions/ruby_core/inventory'
|
|
23
22
|
|
|
24
23
|
# protect
|
|
25
24
|
cs__scoped_require 'contrast/agent/protect/policy/policy'
|
|
26
|
-
cs__scoped_require 'contrast/
|
|
27
|
-
cs__scoped_require 'contrast/
|
|
25
|
+
cs__scoped_require 'contrast/extensions/ruby_core/protect'
|
|
26
|
+
cs__scoped_require 'contrast/extensions/ruby_core/protect/kernel'
|
|
28
27
|
|
|
29
28
|
module Contrast
|
|
30
29
|
module Agent
|
|
@@ -39,7 +38,6 @@ module Contrast
|
|
|
39
38
|
include Contrast::Agent::Assess::Policy::SourceMethod
|
|
40
39
|
include Contrast::Agent::Assess::Policy::PropagationMethod
|
|
41
40
|
include Contrast::Agent::Assess::Policy::TriggerMethod
|
|
42
|
-
extend Contrast::Utils::ScopeUtil
|
|
43
41
|
|
|
44
42
|
include Contrast::Components::Interface
|
|
45
43
|
access_component :logging, :analysis, :agent, :scope
|
|
@@ -50,6 +48,18 @@ module Contrast
|
|
|
50
48
|
Contrast::Agent::Protect::Policy::Policy
|
|
51
49
|
].cs__freeze
|
|
52
50
|
|
|
51
|
+
def enter_method_scope! method_policy
|
|
52
|
+
method_policy.scopes_to_enter.each do |scope|
|
|
53
|
+
enter_scope!(scope)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def exit_method_scope! method_policy
|
|
58
|
+
method_policy.scopes_to_exit.each do |scope|
|
|
59
|
+
exit_scope!(scope)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
53
63
|
# THIS IS CALLED FROM C. Do not change the signature lightly.
|
|
54
64
|
#
|
|
55
65
|
# This method functions to call the infilter methods from our
|
|
@@ -68,18 +78,20 @@ module Contrast
|
|
|
68
78
|
def apply_pre_patch method_policy, method, exception, object, args
|
|
69
79
|
apply_protect(method_policy, method, exception, object, args)
|
|
70
80
|
apply_inventory(method_policy, method, exception, object, args)
|
|
71
|
-
# We were told to block something, so we gotta. Don't catch this
|
|
72
|
-
# one, let it get back to our Middleware or even all the way out to
|
|
73
|
-
# the framework
|
|
74
81
|
rescue Contrast::SecurityException => e
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
|
|
82
|
+
# We were told to block something, so we gotta. Don't catch this
|
|
83
|
+
# one, let it get back to our Middleware or even all the way out to
|
|
84
|
+
# the framework
|
|
78
85
|
raise e
|
|
79
|
-
# Anything else was our bad and we gotta catch that to allow for
|
|
80
|
-
# normal application flow
|
|
81
86
|
rescue StandardError => e
|
|
87
|
+
# Anything else was our bad and we gotta catch that to allow for
|
|
88
|
+
# normal application flow
|
|
82
89
|
logger.error(e, 'Unable to apply pre patch to method.')
|
|
90
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
91
|
+
# This is something like NoMemoryError that we can't
|
|
92
|
+
# hope to handle. Nonetheless, shouldn't leak scope.
|
|
93
|
+
exit_contrast_scope!
|
|
94
|
+
raise e
|
|
83
95
|
end
|
|
84
96
|
|
|
85
97
|
# THIS IS CALLED FROM C. Do not change the signature lightly.
|
|
@@ -197,9 +209,6 @@ module Contrast
|
|
|
197
209
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
198
210
|
logger.error(e, 'Unable to assess method call.')
|
|
199
211
|
handle_return(propagated_ret, source_ret, ret)
|
|
200
|
-
# This will unwind the stack, so we handle our own scope exit.
|
|
201
|
-
# Move this to C when it's convenient.
|
|
202
|
-
exit_contrast_scope!
|
|
203
212
|
raise e
|
|
204
213
|
end
|
|
205
214
|
|
|
@@ -257,13 +266,17 @@ module Contrast
|
|
|
257
266
|
safe_return
|
|
258
267
|
end
|
|
259
268
|
|
|
260
|
-
# Given a
|
|
261
|
-
#
|
|
262
|
-
|
|
269
|
+
# Given a module and method, construct an expected name for the
|
|
270
|
+
# alias by which Contrast will reference the original.
|
|
271
|
+
#
|
|
272
|
+
# @param patched_class [Module] the module being patched
|
|
273
|
+
# @param patched_method [Symbol] the method being patched
|
|
274
|
+
# @return [Symbol]
|
|
275
|
+
def build_method_name patched_class, patched_method
|
|
263
276
|
(Contrast::Utils::ObjectShare::CONTRAST_PATCHED_METHOD_START +
|
|
264
|
-
|
|
277
|
+
patched_class.cs__name.gsub('::', '_').downcase +
|
|
265
278
|
Contrast::Utils::ObjectShare::UNDERSCORE +
|
|
266
|
-
|
|
279
|
+
patched_method.to_s).to_sym
|
|
267
280
|
end
|
|
268
281
|
|
|
269
282
|
# @param mod [Module] the module in which the patch should be
|
|
@@ -302,6 +315,24 @@ module Contrast
|
|
|
302
315
|
def instrument_with_prepend mod, method_policy
|
|
303
316
|
contrast_prepend_method(mod, method_policy)
|
|
304
317
|
end
|
|
318
|
+
|
|
319
|
+
# @return [Boolean]
|
|
320
|
+
def skip_contrast_analysis?
|
|
321
|
+
return true if in_contrast_scope?
|
|
322
|
+
return true unless Contrast::Agent::REQUEST_TRACKER.current&.analyze_request?
|
|
323
|
+
|
|
324
|
+
false
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Skip if we should skip_contrast_analysis?, sampling says to ignore this
|
|
328
|
+
# request, or assess has been disabled.
|
|
329
|
+
#
|
|
330
|
+
# @return [Boolean]
|
|
331
|
+
def skip_assess_analysis?
|
|
332
|
+
return true if skip_contrast_analysis?
|
|
333
|
+
|
|
334
|
+
!ASSESS.enabled?
|
|
335
|
+
end
|
|
305
336
|
end
|
|
306
337
|
end
|
|
307
338
|
end
|
|
@@ -7,10 +7,8 @@ cs__scoped_require 'monitor'
|
|
|
7
7
|
cs__scoped_require 'contrast/agent/patching/policy/patch_status'
|
|
8
8
|
cs__scoped_require 'contrast/agent/patching/policy/method_policy'
|
|
9
9
|
cs__scoped_require 'contrast/agent/patching/policy/module_policy'
|
|
10
|
-
cs__scoped_require 'contrast/agent/patching/policy/policy_unpatcher'
|
|
11
10
|
cs__scoped_require 'contrast/components/interface'
|
|
12
11
|
cs__scoped_require 'contrast/utils/class_util'
|
|
13
|
-
cs__scoped_require 'contrast/utils/scope_util'
|
|
14
12
|
|
|
15
13
|
# assess
|
|
16
14
|
cs__scoped_require 'contrast/agent/assess/policy/policy'
|
|
@@ -43,7 +41,6 @@ module Contrast
|
|
|
43
41
|
# provides a map for which methods our renamed functions need to call
|
|
44
42
|
# and how.
|
|
45
43
|
module Patcher
|
|
46
|
-
extend Contrast::Utils::ScopeUtil
|
|
47
44
|
extend Contrast::Agent::Patching::Policy::AfterLoadPatcher
|
|
48
45
|
|
|
49
46
|
include Contrast::Components::Interface
|
|
@@ -58,7 +55,6 @@ module Contrast
|
|
|
58
55
|
catchup_after_load_patches
|
|
59
56
|
patch_methods
|
|
60
57
|
Contrast::Agent::Assess::Policy::RewriterPatch.rewrite_interpolations
|
|
61
|
-
Contrast::Agent::Patching::Policy::PolicyUnpatcher.revert_conflicting_patches
|
|
62
58
|
end
|
|
63
59
|
end
|
|
64
60
|
|
|
@@ -84,7 +80,8 @@ module Contrast
|
|
|
84
80
|
# or eval of dynamic class definition
|
|
85
81
|
def patch_specific_module mod
|
|
86
82
|
mod_name = mod.cs__name
|
|
87
|
-
return unless
|
|
83
|
+
return unless Contrast::Utils::ClassUtil.truly_defined?(mod_name)
|
|
84
|
+
return if AGENT.skip_instrumentation?(mod_name)
|
|
88
85
|
|
|
89
86
|
load_patches_for_module(mod_name)
|
|
90
87
|
|
|
@@ -137,7 +134,7 @@ module Contrast
|
|
|
137
134
|
# @param name [String] the constant whose value should be retrieved
|
|
138
135
|
# @return [Object, nil]
|
|
139
136
|
def patchable name
|
|
140
|
-
return unless
|
|
137
|
+
return unless Contrast::Utils::ClassUtil.truly_defined?(name)
|
|
141
138
|
|
|
142
139
|
Module.cs__const_get(name)
|
|
143
140
|
end
|
|
@@ -156,6 +153,8 @@ module Contrast
|
|
|
156
153
|
# logger.trace_with_time("\t\tRunning patching") do # TODO: RUBY-547
|
|
157
154
|
patched = []
|
|
158
155
|
all_module_names.each do |patchable_name|
|
|
156
|
+
next if AGENT.skip_instrumentation?(patchable_name)
|
|
157
|
+
|
|
159
158
|
patchable_mod = patchable(patchable_name)
|
|
160
159
|
next unless patchable_mod
|
|
161
160
|
|
|
@@ -301,10 +300,10 @@ module Contrast
|
|
|
301
300
|
end
|
|
302
301
|
|
|
303
302
|
# core extensions
|
|
304
|
-
cs__scoped_require 'contrast/
|
|
305
|
-
cs__scoped_require 'contrast/
|
|
306
|
-
cs__scoped_require 'contrast/
|
|
307
|
-
cs__scoped_require 'contrast/
|
|
308
|
-
cs__scoped_require 'contrast/
|
|
303
|
+
cs__scoped_require 'contrast/extensions/ruby_core/module'
|
|
304
|
+
cs__scoped_require 'contrast/extensions/ruby_core/assess'
|
|
305
|
+
cs__scoped_require 'contrast/extensions/ruby_core/inventory'
|
|
306
|
+
cs__scoped_require 'contrast/extensions/ruby_core/protect'
|
|
307
|
+
cs__scoped_require 'contrast/extensions/ruby_core/protect/kernel'
|
|
309
308
|
|
|
310
309
|
cs__scoped_require 'cs__contrast_patch/cs__contrast_patch'
|