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
data/lib/contrast/api.rb
CHANGED
|
@@ -12,6 +12,7 @@ end
|
|
|
12
12
|
|
|
13
13
|
cs__scoped_require 'contrast/api/dtm_pb'
|
|
14
14
|
cs__scoped_require 'contrast/api/settings_pb'
|
|
15
|
+
cs__scoped_require 'contrast/delegators'
|
|
15
16
|
cs__scoped_require 'contrast/api/unix_socket'
|
|
16
17
|
cs__scoped_require 'contrast/api/tcp_socket'
|
|
17
18
|
cs__scoped_require 'contrast/api/speedracer'
|
|
@@ -133,8 +133,8 @@ module Contrast
|
|
|
133
133
|
message.prefilter = event
|
|
134
134
|
when Contrast::Api::Dtm::HttpResponse
|
|
135
135
|
message.postfilter = event
|
|
136
|
-
when Contrast::Api::Dtm::
|
|
137
|
-
message.
|
|
136
|
+
when Contrast::Api::Dtm::Poll
|
|
137
|
+
message.poll = event
|
|
138
138
|
when Contrast::Api::Dtm::ObservedRoute
|
|
139
139
|
message.observed_route = event
|
|
140
140
|
else
|
|
@@ -1,6 +1,8 @@
|
|
|
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 'rubygems/version'
|
|
5
|
+
|
|
4
6
|
module Contrast
|
|
5
7
|
module Components
|
|
6
8
|
module Agent
|
|
@@ -46,6 +48,10 @@ module Contrast
|
|
|
46
48
|
!interpolation_patch_possible?
|
|
47
49
|
end
|
|
48
50
|
|
|
51
|
+
def patch_yield?
|
|
52
|
+
!Contrast::Utils::BooleanUtil.false?(CONFIG.root.agent.ruby.propagate_yield)
|
|
53
|
+
end
|
|
54
|
+
|
|
49
55
|
def interpolation_enabled?
|
|
50
56
|
!Contrast::Utils::BooleanUtil.false?(CONFIG.root.agent.ruby.interpolate)
|
|
51
57
|
end
|
|
@@ -54,12 +60,15 @@ module Contrast
|
|
|
54
60
|
Contrast::Agent::FeatureState.instance.report_custom_code_sysfile_access?
|
|
55
61
|
end
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
def skip_instrumentation? loaded_module_name
|
|
64
|
+
return true unless loaded_module_name
|
|
65
|
+
|
|
66
|
+
loaded_module_name.start_with?(*CONFIG.root.agent.ruby.uninstrument_namespace)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# All this method chain does anymore is load the Thread patch that
|
|
70
|
+
# propagates request contexts. That can go away RUBY-700.
|
|
71
|
+
SHARED_LIBRARIES = %w[contrast/extensions/ruby_core/thread].cs__freeze
|
|
63
72
|
def run_instrumentation
|
|
64
73
|
Contrast::Agent::FeatureState.instance.tap do |settings|
|
|
65
74
|
SHARED_LIBRARIES.each { |lib| settings.instrument lib }
|
|
@@ -68,14 +77,24 @@ module Contrast
|
|
|
68
77
|
enable_tracepoint # This handles all class loads & required instrumentation going forward
|
|
69
78
|
end
|
|
70
79
|
|
|
80
|
+
# TODO: RUBY-564: This responsibility should be extracted out of this agent component and moved to
|
|
81
|
+
# the new component that handles one-time-whole-app initialization procedures.
|
|
82
|
+
def insert_middleware app
|
|
83
|
+
app.middleware.insert_before 0, Contrast::Agent::Middleware # Keep our middleware at the outermost layer of the onion
|
|
84
|
+
end
|
|
85
|
+
|
|
71
86
|
def enable_tracepoint
|
|
72
87
|
Contrast::Agent::TracePointHook.enable!
|
|
73
88
|
end
|
|
74
89
|
|
|
75
90
|
protected
|
|
76
91
|
|
|
92
|
+
INTERPOLATION_HOOKABLE_VERSION = Gem::Version.new('2.6.0')
|
|
93
|
+
# Ruby exposed the C method for interpolation in version 2.6.0, meaning
|
|
94
|
+
# we can attempt to patch using Funchook for that version and later.
|
|
77
95
|
def interpolation_patch_possible?
|
|
78
|
-
Gem::Version.new(RUBY_VERSION) >=
|
|
96
|
+
@_interpolation_patch_possible = Gem::Version.new(RUBY_VERSION) >= INTERPOLATION_HOOKABLE_VERSION if @_interpolation_patch_possible.nil?
|
|
97
|
+
@_interpolation_patch_possible
|
|
79
98
|
end
|
|
80
99
|
end
|
|
81
100
|
|
|
@@ -1,8 +1,8 @@
|
|
|
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/core_extensions/object'
|
|
5
4
|
cs__scoped_require 'contrast/utils/sinatra_helper'
|
|
5
|
+
cs__scoped_require 'rubygems/version'
|
|
6
6
|
|
|
7
7
|
module Contrast
|
|
8
8
|
module Components
|
|
@@ -23,12 +23,6 @@ module Contrast
|
|
|
23
23
|
DEFAULT_SERVER_NAME = 'localhost'
|
|
24
24
|
DEFAULT_SERVER_PATH = '/'
|
|
25
25
|
|
|
26
|
-
RAILS_TYPE = 'rails'
|
|
27
|
-
SINATRA_TYPE = 'sinatra'
|
|
28
|
-
RACK_TYPE = 'rack'
|
|
29
|
-
|
|
30
|
-
RAILS_MODULE_NAME_VERSION = Gem::Version.new('6.0.0')
|
|
31
|
-
|
|
32
26
|
def present? str
|
|
33
27
|
Contrast::Utils::EnvironmentUtil.present?(str)
|
|
34
28
|
end
|
|
@@ -36,29 +30,17 @@ module Contrast
|
|
|
36
30
|
def server_type
|
|
37
31
|
@_server_type ||= begin
|
|
38
32
|
tmp = CONFIG.root.server.type
|
|
39
|
-
tmp =
|
|
33
|
+
tmp = Contrast::Agent.framework_manager.server_type unless present?(tmp)
|
|
40
34
|
tmp
|
|
41
35
|
rescue StandardError
|
|
42
36
|
RACK_TYPE
|
|
43
37
|
end
|
|
44
38
|
end
|
|
45
39
|
|
|
46
|
-
def framework_server_name
|
|
47
|
-
@_framework_server_name ||= begin
|
|
48
|
-
if defined?(Rails)
|
|
49
|
-
RAILS_TYPE
|
|
50
|
-
elsif defined?(Sinatra)
|
|
51
|
-
SINATRA_TYPE
|
|
52
|
-
else
|
|
53
|
-
RACK_TYPE
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
40
|
def name
|
|
59
41
|
@_name ||= begin
|
|
60
42
|
tmp = CONFIG.root.application.name
|
|
61
|
-
tmp =
|
|
43
|
+
tmp = Contrast::Agent.framework_manager.app_name unless present?(tmp)
|
|
62
44
|
tmp = File.basename(Dir.pwd) unless present?(tmp)
|
|
63
45
|
Contrast::Utils::StringUtils.truncate(tmp, DEFAULT_APP_NAME)
|
|
64
46
|
rescue StandardError
|
|
@@ -66,14 +48,6 @@ module Contrast
|
|
|
66
48
|
end
|
|
67
49
|
end
|
|
68
50
|
|
|
69
|
-
def framework_app_name
|
|
70
|
-
@_framework_app_name ||= begin
|
|
71
|
-
name = find_rails_app_name
|
|
72
|
-
name ||= find_sinatra_app_name
|
|
73
|
-
name
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
51
|
def path
|
|
78
52
|
@_path ||= begin
|
|
79
53
|
tmp = CONFIG.root.application.path
|
|
@@ -154,24 +128,13 @@ module Contrast
|
|
|
154
128
|
@_client_id ||= [name, pgid].join('-')
|
|
155
129
|
end
|
|
156
130
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def
|
|
160
|
-
|
|
161
|
-
return unless sinatra_app
|
|
162
|
-
|
|
163
|
-
sinatra_app.cs__class.cs__name
|
|
131
|
+
# TODO: RUBY-564: This responsibility should be extracted out of app_context and moved to
|
|
132
|
+
# the new component that handles one-time-whole-app initialization procedures.
|
|
133
|
+
def instrument_middleware_stack?
|
|
134
|
+
!Contrast::Utils::JobServersRunning.job_servers_running?
|
|
164
135
|
end
|
|
165
136
|
|
|
166
|
-
|
|
167
|
-
return nil unless defined?(Rails)
|
|
168
|
-
|
|
169
|
-
# Rails version 6.0.0 deprecated Rails::Application#parent_name, in Rails 6.1.0 that method will be removed entirely
|
|
170
|
-
# and instead we need to use parent_module_name
|
|
171
|
-
return Rails.application.cs__class.parent_module_name if Gem::Version.new(Rails.version) >= RAILS_MODULE_NAME_VERSION
|
|
172
|
-
|
|
173
|
-
Rails.application.cs__class.parent_name
|
|
174
|
-
end
|
|
137
|
+
private
|
|
175
138
|
|
|
176
139
|
# TODO: RUBY-120, move this responsibility toward the protobuf object
|
|
177
140
|
def protobuf_format param, truncate: true
|
|
@@ -65,12 +65,11 @@ module Contrast
|
|
|
65
65
|
# should be "must not be false" -- oops.
|
|
66
66
|
!false?(CONFIG.root.agent.start_bundled_service) &&
|
|
67
67
|
# Either a valid host or a valid socket
|
|
68
|
-
(CONFIG.root.agent.service.host.nil? ||
|
|
68
|
+
((CONFIG.root.agent.service.host.nil? ||
|
|
69
69
|
CONFIG.root.agent.service.host == 'localhost' ||
|
|
70
|
-
CONFIG.root.agent.service.host == '127.0.0.1' ||
|
|
71
|
-
CONFIG.root.agent.service.host.empty?) ||
|
|
70
|
+
CONFIG.root.agent.service.host == '127.0.0.1') ||
|
|
72
71
|
# Path validity is the service's problem
|
|
73
|
-
|
|
72
|
+
!!CONFIG.root.agent.service.socket)
|
|
74
73
|
end
|
|
75
74
|
end
|
|
76
75
|
|
|
@@ -39,33 +39,13 @@ module Contrast
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
module InstanceMethods # :nodoc:
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
# [:my_cool_scope, :another_good_one].each do |scope|
|
|
45
|
-
# define_method "in_#{scope}_scope?" do
|
|
46
|
-
# abc
|
|
47
|
-
# end
|
|
48
|
-
# end
|
|
49
|
-
|
|
50
|
-
def in_contrast_scope?
|
|
51
|
-
scope_for_current_ec.in_contrast_scope?
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def enter_contrast_scope!
|
|
55
|
-
scope_for_current_ec.enter_scope_for Contrast::Agent::Scope::CONTRAST_SCOPE
|
|
56
|
-
scope_for_current_ec
|
|
57
|
-
end
|
|
42
|
+
# For each instance method on a scope, define a forwarder
|
|
43
|
+
# to the scope on the current execution context's scope.
|
|
58
44
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def with_contrast_scope
|
|
65
|
-
enter_contrast_scope!
|
|
66
|
-
yield
|
|
67
|
-
ensure
|
|
68
|
-
exit_contrast_scope!
|
|
45
|
+
Contrast::Agent::Scope.public_instance_methods(false).each do |method_sym|
|
|
46
|
+
define_method(method_sym) do |*args, &block|
|
|
47
|
+
scope_for_current_ec.send(method_sym, *args, &block)
|
|
48
|
+
end
|
|
69
49
|
end
|
|
70
50
|
|
|
71
51
|
def scope_for_current_ec
|
|
@@ -104,3 +84,53 @@ module Contrast
|
|
|
104
84
|
end
|
|
105
85
|
end
|
|
106
86
|
end
|
|
87
|
+
|
|
88
|
+
# This is a reasonable place for the Kernel#catch hook to live.
|
|
89
|
+
# No current plans for component re-design, but if we had some kind of
|
|
90
|
+
# "do this when a component is hooked in" thing, this would live there.
|
|
91
|
+
# For now, it's over-engineering to live anywhere else. -ajm
|
|
92
|
+
module Kernel # :nodoc:
|
|
93
|
+
alias_method :cs__catch, :catch
|
|
94
|
+
|
|
95
|
+
# In the event of a `throw`, we need to override `catch`
|
|
96
|
+
# to save & restore scope state:
|
|
97
|
+
#
|
|
98
|
+
# scope_level == 0
|
|
99
|
+
#
|
|
100
|
+
# catch(:abc) do
|
|
101
|
+
# with_contrast_scope do
|
|
102
|
+
# throw :abc # will leak
|
|
103
|
+
# end
|
|
104
|
+
# end
|
|
105
|
+
#
|
|
106
|
+
# scope_level == 1
|
|
107
|
+
#
|
|
108
|
+
# Frankly, this isn't how scope should be used. This is in place of
|
|
109
|
+
# proper `ensure` blocks within the instrumentation call stack.
|
|
110
|
+
# This will actually /create/ scope leaks if you're doing something like:
|
|
111
|
+
#
|
|
112
|
+
# catch(:ohno) do
|
|
113
|
+
# enter scope
|
|
114
|
+
# end
|
|
115
|
+
#
|
|
116
|
+
# abc()
|
|
117
|
+
#
|
|
118
|
+
# exit scope
|
|
119
|
+
#
|
|
120
|
+
# i.e. if you intend to change net scope across a catch block boundary.
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
def catch *args, &block
|
|
125
|
+
# Save current scope level
|
|
126
|
+
scope_level = Contrast::Components::Scope::COMPONENT_INTERFACE.scope_for_current_ec.instance_variable_get(:@contrast_scope)
|
|
127
|
+
|
|
128
|
+
# Run original catch with block.
|
|
129
|
+
retval = cs__catch(*args, &block)
|
|
130
|
+
|
|
131
|
+
# Restore scope.
|
|
132
|
+
Contrast::Components::Scope::COMPONENT_INTERFACE.scope_for_current_ec.instance_variable_set(:@contrast_scope, scope_level)
|
|
133
|
+
|
|
134
|
+
retval
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -25,9 +25,14 @@ module Contrast
|
|
|
25
25
|
KEYS = {
|
|
26
26
|
disabled_agent_rake_tasks: Contrast::Config::DefaultValue.new(DISABLED_RAKE_TASK_LIST),
|
|
27
27
|
exceptions: Contrast::Config::ExceptionConfiguration,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
# controls whether or not we patch interpolation, either by rewrite or by funchook
|
|
29
|
+
interpolate: Contrast::Config::DefaultValue.new(Contrast::Utils::ObjectShare::TRUE),
|
|
30
|
+
# controls whether or not we patch the rb_yield block to track split propagation
|
|
31
|
+
propagate_yield: Contrast::Config::DefaultValue.new(Contrast::Utils::ObjectShare::TRUE),
|
|
32
|
+
# control whether or not we run file scanning rules on require
|
|
33
|
+
require_scan: Contrast::Config::DefaultValue.new(Contrast::Utils::ObjectShare::TRUE),
|
|
34
|
+
# controls whether or not we track frozen Strings by replacing them
|
|
35
|
+
track_frozen_sources: Contrast::Config::DefaultValue.new(Contrast::Utils::ObjectShare::TRUE),
|
|
31
36
|
uninstrument_namespace: Contrast::Config::DefaultValue.new(DEFAULT_UNINSTRUMENTED_NAMESPACES)
|
|
32
37
|
}.cs__freeze
|
|
33
38
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
# Used to define decorators for objects to add behavior without polluting the namespace
|
|
6
|
+
module Delegators
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
cs__scoped_require 'contrast/delegators/application_update'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Delegators
|
|
6
|
+
# Used to decorate the ApplicationUpdate protobuf model so it can own some of the data massaging required for
|
|
7
|
+
# AppUpdate dtm
|
|
8
|
+
class ApplicationUpdate < SimpleDelegator
|
|
9
|
+
def append_view_technology_descriptor_data view_technology_descriptors
|
|
10
|
+
view_technology_descriptors.each do |vtd|
|
|
11
|
+
vtd.technology_names.each do |tech_name|
|
|
12
|
+
@delegate_sd_obj.technologies[tech_name] = true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# TS only allows you to report 500 routes per application
|
|
18
|
+
def append_route_coverage_data route_coverage_dtms
|
|
19
|
+
route_coverage_dtms.take(500).each do |route_coverage_dtm|
|
|
20
|
+
@delegate_sd_obj.routes << route_coverage_dtm
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def append_platform_version platform_version
|
|
25
|
+
@delegate_sd_obj.platform = Contrast::Api::Dtm::Platform.new if @delegate_sd_obj.platform.nil?
|
|
26
|
+
@delegate_sd_obj.platform.major = platform_version.major
|
|
27
|
+
@delegate_sd_obj.platform.minor = platform_version.minor
|
|
28
|
+
@delegate_sd_obj.platform.build = platform_version.patch
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
cs__scoped_require 'contrast/components/interface'
|
|
5
|
+
|
|
6
|
+
module Rack
|
|
7
|
+
module Session
|
|
8
|
+
# Our patch into the Rack::Session::Cookie Class, allowing for the
|
|
9
|
+
# runtime detection of insecure configurations on individual cookies
|
|
10
|
+
# within the application
|
|
11
|
+
class Cookie
|
|
12
|
+
include Contrast::Utils::InvalidConfigurationUtil
|
|
13
|
+
include Contrast::Components::Interface
|
|
14
|
+
|
|
15
|
+
access_component :scope
|
|
16
|
+
|
|
17
|
+
alias_method :cs__patched_initialize, :initialize
|
|
18
|
+
def initialize app, options = {}
|
|
19
|
+
Contrast::Utils::RackAssessSessionCookie.analyze_cookie_initialization(options)
|
|
20
|
+
cs__patched_initialize(app, options)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# In earlier versions of rack < 2.0.0 the Rack::Response and Rack::Request do
|
|
5
|
+
# not have get_header or set_header methods. This is our way of working
|
|
6
|
+
# around that.
|
|
7
|
+
module Rack
|
|
8
|
+
# Our patch into the Rack::Request class, allowing us to call set_header
|
|
9
|
+
# and get_header in our code without worrying about older versions of
|
|
10
|
+
# Rack not implementing these methods.
|
|
11
|
+
class Request
|
|
12
|
+
unless Rack::Request.instance_methods(true).include?(:set_header)
|
|
13
|
+
def set_header name, value
|
|
14
|
+
@env[name] = value
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
unless Rack::Request.instance_methods(true).include?(:get_header)
|
|
19
|
+
def get_header name
|
|
20
|
+
@env[name]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# In earlier versions of rack < 2.0.0 the Rack::Response and Rack::Request do
|
|
5
|
+
# not have get_header or set_header methods. This is our way of working
|
|
6
|
+
# around that.
|
|
7
|
+
module Rack
|
|
8
|
+
# Our patch into the Rack::Response Class, allowing us to call set_header
|
|
9
|
+
# and get_header in our code without worrying about older versions of
|
|
10
|
+
# Rack not implementing these methods.
|
|
11
|
+
class Response
|
|
12
|
+
unless Rack::Response.instance_methods(true).include?(:set_header)
|
|
13
|
+
def set_header key, value
|
|
14
|
+
headers[key] = value
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
unless Rack::Response.instance_methods(true).include?(:get_header)
|
|
18
|
+
def get_header key
|
|
19
|
+
headers[key]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|