contrast-agent 4.3.1 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.simplecov +1 -1
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/Rakefile +1 -1
- data/exe/contrast_service +1 -1
- data/ext/build_funchook.rb +1 -1
- 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 +1 -1
- 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 +1 -10
- data/lib/contrast/agent/assess/contrast_event.rb +54 -71
- data/lib/contrast/agent/assess/contrast_object.rb +6 -3
- data/lib/contrast/agent/assess/events/event_factory.rb +1 -1
- 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 +30 -15
- data/lib/contrast/agent/assess/policy/patcher.rb +1 -1
- data/lib/contrast/agent/assess/policy/policy.rb +1 -1
- data/lib/contrast/agent/assess/policy/policy_node.rb +1 -1
- 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 +30 -19
- data/lib/contrast/agent/assess/policy/propagation_node.rb +1 -1
- 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 +1 -1
- 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 +1 -1
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +1 -1
- 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 +1 -1
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +24 -14
- data/lib/contrast/agent/assess/policy/propagator/split.rb +15 -8
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +31 -15
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +66 -35
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +1 -1
- data/lib/contrast/agent/assess/policy/source_method.rb +87 -76
- 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 +1 -1
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +3 -3
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +7 -8
- data/lib/contrast/agent/assess/policy/trigger_method.rb +106 -64
- data/lib/contrast/agent/assess/policy/trigger_node.rb +31 -10
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +59 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +2 -3
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +7 -5
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +3 -5
- data/lib/contrast/agent/assess/properties.rb +1 -3
- data/lib/contrast/agent/assess/property/evented.rb +1 -1
- 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 +1 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +1 -1
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +1 -1
- 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 +1 -1
- 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 +1 -1
- data/lib/contrast/agent/exclusion_matcher.rb +1 -1
- data/lib/contrast/agent/inventory.rb +1 -2
- data/lib/contrast/agent/inventory/dependencies.rb +1 -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 +112 -109
- data/lib/contrast/agent/module_data.rb +1 -1
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +1 -1
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +5 -1
- data/lib/contrast/agent/patching/policy/method_policy.rb +1 -1
- data/lib/contrast/agent/patching/policy/module_policy.rb +1 -1
- data/lib/contrast/agent/patching/policy/patch.rb +12 -13
- data/lib/contrast/agent/patching/policy/patch_status.rb +2 -2
- data/lib/contrast/agent/patching/policy/patcher.rb +59 -54
- data/lib/contrast/agent/patching/policy/policy.rb +14 -21
- data/lib/contrast/agent/patching/policy/policy_node.rb +1 -1
- data/lib/contrast/agent/patching/policy/trigger_node.rb +6 -3
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
- data/lib/contrast/agent/protect/policy/policy.rb +1 -1
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +1 -1
- 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 +7 -18
- data/lib/contrast/agent/protect/rule/base_service.rb +2 -2
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +2 -2
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +1 -1
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +1 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +2 -2
- data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -1
- data/lib/contrast/agent/protect/rule/sqli.rb +18 -12
- 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 +1 -1
- data/lib/contrast/agent/protect/rule/xss.rb +1 -1
- data/lib/contrast/agent/protect/rule/xxe.rb +1 -1
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +1 -1
- data/lib/contrast/agent/railtie.rb +1 -1
- data/lib/contrast/agent/reaction_processor.rb +1 -1
- data/lib/contrast/agent/request.rb +2 -1
- data/lib/contrast/agent/request_context.rb +17 -10
- data/lib/contrast/agent/request_handler.rb +1 -1
- data/lib/contrast/agent/response.rb +1 -1
- data/lib/contrast/agent/rewriter.rb +1 -1
- data/lib/contrast/agent/rule_set.rb +3 -3
- data/lib/contrast/agent/scope.rb +1 -1
- data/lib/contrast/agent/service_heartbeat.rb +1 -1
- 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 +1 -1
- 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 +11 -4
- data/lib/contrast/api/communication/service_lifecycle.rb +1 -1
- data/lib/contrast/api/communication/socket.rb +1 -1
- data/lib/contrast/api/communication/socket_client.rb +23 -15
- data/lib/contrast/api/communication/speedracer.rb +3 -3
- 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 +53 -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 +1 -1
- data/lib/contrast/api/decorators/library_usage_update.rb +1 -1
- data/lib/contrast/api/decorators/message.rb +1 -1
- 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 +43 -15
- data/lib/contrast/api/decorators/trace_event_object.rb +1 -1
- 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 +1 -1
- data/lib/contrast/api/decorators/user_input.rb +1 -1
- data/lib/contrast/components/agent.rb +7 -11
- data/lib/contrast/components/app_context.rb +5 -23
- data/lib/contrast/components/assess.rb +6 -11
- data/lib/contrast/components/config.rb +1 -1
- data/lib/contrast/components/contrast_service.rb +1 -1
- data/lib/contrast/components/heap_dump.rb +1 -1
- data/lib/contrast/components/interface.rb +1 -1
- 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 +49 -7
- data/lib/contrast/components/scope.rb +2 -1
- data/lib/contrast/components/settings.rb +27 -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 +1 -1
- data/lib/contrast/config/base_configuration.rb +1 -1
- data/lib/contrast/config/default_value.rb +1 -1
- data/lib/contrast/config/exception_configuration.rb +1 -1
- data/lib/contrast/config/heap_dump_configuration.rb +1 -1
- data/lib/contrast/config/inventory_configuration.rb +1 -1
- data/lib/contrast/config/logger_configuration.rb +1 -1
- 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 +1 -1
- data/lib/contrast/delegators/input_analysis.rb +12 -0
- data/lib/contrast/extension/assess.rb +1 -1
- data/lib/contrast/extension/assess/array.rb +1 -1
- data/lib/contrast/extension/assess/erb.rb +1 -1
- data/lib/contrast/extension/assess/eval_trigger.rb +1 -5
- data/lib/contrast/extension/assess/exec_trigger.rb +1 -5
- data/lib/contrast/extension/assess/fiber.rb +1 -1
- data/lib/contrast/extension/assess/hash.rb +1 -1
- data/lib/contrast/extension/assess/kernel.rb +1 -1
- data/lib/contrast/extension/assess/marshal.rb +1 -5
- data/lib/contrast/extension/assess/regexp.rb +1 -1
- data/lib/contrast/extension/assess/string.rb +1 -1
- data/lib/contrast/extension/delegator.rb +1 -1
- data/lib/contrast/extension/inventory.rb +1 -1
- data/lib/contrast/extension/kernel.rb +1 -1
- 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 +13 -15
- data/lib/contrast/framework/platform_version.rb +1 -1
- data/lib/contrast/framework/rack/patch/session_cookie.rb +1 -1
- data/lib/contrast/framework/rack/patch/support.rb +1 -1
- 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 +1 -1
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +4 -4
- data/lib/contrast/framework/rails/patch/support.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +1 -1
- data/lib/contrast/framework/rails/support.rb +43 -44
- data/lib/contrast/framework/sinatra/support.rb +101 -42
- data/lib/contrast/funchook/funchook.rb +1 -1
- data/lib/contrast/logger/application.rb +1 -1
- data/lib/contrast/logger/format.rb +1 -1
- data/lib/contrast/logger/log.rb +32 -16
- data/lib/contrast/logger/request.rb +1 -1
- data/lib/contrast/logger/time.rb +1 -1
- data/lib/contrast/security_exception.rb +1 -1
- data/lib/contrast/tasks/config.rb +1 -1
- data/lib/contrast/tasks/service.rb +1 -1
- data/lib/contrast/utils/assess/sampling_util.rb +1 -1
- data/lib/contrast/utils/assess/tracking_util.rb +1 -1
- data/lib/contrast/utils/class_util.rb +18 -4
- 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 +14 -19
- 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 +1 -1
- data/lib/contrast/utils/job_servers_running.rb +1 -1
- data/lib/contrast/utils/object_share.rb +1 -1
- data/lib/contrast/utils/os.rb +1 -1
- 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 +1 -1
- 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 +59 -19
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +134 -137
- 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/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'
|
@@ -27,15 +27,11 @@ module Contrast
|
|
27
27
|
|
28
28
|
def cs__load_assess source, ret
|
29
29
|
with_contrast_scope do
|
30
|
-
current_context = Contrast::Agent::REQUEST_TRACKER.current
|
31
|
-
return unless current_context
|
32
|
-
|
33
30
|
args = [source]
|
34
31
|
# source might not be all the args passed in, but it is the one we care
|
35
32
|
# about. we could pass in all the args in the last param here if it
|
36
33
|
# becomes an issue in rendering on TS
|
37
34
|
Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(
|
38
|
-
current_context,
|
39
35
|
trigger_node('Marshal', :load),
|
40
36
|
source,
|
41
37
|
self,
|
@@ -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/propagation_node'
|
@@ -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/propagation_node'
|
@@ -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
|
# Some developers override various methods on Delegator, which can often
|
@@ -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
|
module Contrast
|
@@ -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/scope'
|
@@ -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/utils/object_share'
|
@@ -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
|
module Contrast
|
@@ -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
|
if defined?(Psych)
|
@@ -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
|
# ensure that we're being loaded with an agent
|
@@ -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
|
module Contrast
|
@@ -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/framework/platform_version'
|
@@ -44,11 +44,9 @@ module Contrast
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
# Return all the After Load Patches for all the Frameworks we know, even
|
48
|
-
# if that Framework hasn't been detected.
|
47
|
+
# Return all the After Load Patches for all the Frameworks we know, even if that Framework hasn't been detected.
|
49
48
|
#
|
50
|
-
# @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>] the
|
51
|
-
# AfterLoadPatches of each framework
|
49
|
+
# @return [Set<Contrast::Agent::Patching::Policy::AfterLoadPatch>] the AfterLoadPatches of each framework
|
52
50
|
def find_after_load_patches
|
53
51
|
patches = Set.new
|
54
52
|
SUPPORTED_FRAMEWORKS.each do |framework|
|
@@ -82,8 +80,10 @@ module Contrast
|
|
82
80
|
end
|
83
81
|
|
84
82
|
# If we have 0 or n > 1 frameworks, we need to use the default rack request
|
85
|
-
#
|
86
|
-
#
|
83
|
+
#
|
84
|
+
# @param env [Hash] the various variables stored by this and other Middlewares to know the state and values
|
85
|
+
# of this particular Request
|
86
|
+
# @return [::Rack::Request] either a rack request or subclass thereof.
|
87
87
|
def retrieve_request env
|
88
88
|
return @_frameworks[0].retrieve_request(env) if @_frameworks.length == 1
|
89
89
|
|
@@ -102,15 +102,13 @@ module Contrast
|
|
102
102
|
result
|
103
103
|
end
|
104
104
|
|
105
|
+
# Iterate through current frameworks and return the current request's route. This will be the first
|
106
|
+
# non-nil result.
|
107
|
+
#
|
108
|
+
# @param request [Contrast::Agent::Request] the current request.
|
109
|
+
# @return [Contrast::Api::Dtm::RouteCoverage] the current route as a Dtm.
|
105
110
|
def get_route_dtm request
|
106
|
-
|
107
|
-
@_frameworks.find do |framework_klass|
|
108
|
-
# TODO: RUBY-763 Sinatra::Base#call patch adds the Route report
|
109
|
-
next if framework_klass == Contrast::Framework::Sinatra::Support
|
110
|
-
|
111
|
-
result = framework_klass.current_route(request)
|
112
|
-
end
|
113
|
-
result
|
111
|
+
@_frameworks.lazy.map { |framework_support| framework_support.current_route(request) }.reject(&:nil?).first
|
114
112
|
end
|
115
113
|
|
116
114
|
private
|
@@ -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
|
module Contrast
|
@@ -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/agent/patching/policy/after_load_patch'
|
@@ -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/framework/base_support'
|
@@ -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
|
module Contrast
|
@@ -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/framework/rails/patch/assess_configuration'
|
@@ -15,9 +15,9 @@ module Contrast
|
|
15
15
|
@_instrument ||= begin
|
16
16
|
::Rails::Application::Configuration.class_eval do
|
17
17
|
alias_method :cs__patched_session_store, :session_store
|
18
|
-
def session_store *args
|
19
|
-
ret = cs__patched_session_store(*args)
|
20
|
-
Contrast::Framework::Rails::Patch::AssessConfiguration.analyze_session_store(*args)
|
18
|
+
def session_store *args, **kwargs
|
19
|
+
ret = cs__patched_session_store(*args, **kwargs)
|
20
|
+
Contrast::Framework::Rails::Patch::AssessConfiguration.analyze_session_store(*args, **kwargs)
|
21
21
|
ret
|
22
22
|
end
|
23
23
|
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/framework/rails/patch/rails_application_configuration'
|
@@ -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
|
module Contrast
|
@@ -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
|
module Contrast
|
@@ -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
|
module Contrast
|
@@ -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/api/dtm.pb'
|
@@ -47,32 +47,34 @@ module Contrast
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Find the current route, based on the provided Request wrapper
|
50
|
+
#
|
50
51
|
# @param request[Contrast::Agent::Request]
|
51
52
|
# @return [Contrast::Api::Dtm::RouteCoverage]
|
52
53
|
def current_route request
|
53
54
|
return unless ::Rails.cs__respond_to?(:application)
|
54
55
|
|
55
|
-
|
56
|
-
# precedence
|
57
|
-
# match_data: ActionDispatch::Journey::Path::Pattern::MatchData
|
58
|
-
# path_parameters: hash of various things
|
59
|
-
# route: ActionDispatch::Journey::Route
|
60
|
-
full_routes = ::Rails.application.routes.router.send(:find_routes, request.rack_request)
|
61
|
-
return if full_routes.empty?
|
56
|
+
match, _params, route, path = get_full_route(request.rack_request)
|
62
57
|
|
63
|
-
|
58
|
+
original_url = request.rack_request.path_info
|
64
59
|
|
65
|
-
# the route
|
66
|
-
if
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
60
|
+
# Route is either the final rails route, or a router that points to a Sinatra controller.
|
61
|
+
if Contrast::Framework::Sinatra::Support.sinatra_controller?(route.app.app)
|
62
|
+
# Create a request copied from current request, but with the base path removed from path_info.
|
63
|
+
new_req = ::ActionDispatch::Request.new(request.env)
|
64
|
+
new_req.path_info = new_req.path_info.gsub((path << match).join, '')
|
65
|
+
|
66
|
+
return Contrast::Framework::Sinatra::Support.current_route(new_req, route.app.app, original_url)
|
71
67
|
end
|
68
|
+
|
69
|
+
Contrast::Api::Dtm::RouteCoverage.from_action_dispatch_journey(route, original_url)
|
72
70
|
rescue StandardError => _e
|
73
71
|
nil
|
74
72
|
end
|
75
73
|
|
74
|
+
# Copy a request for modification.
|
75
|
+
#
|
76
|
+
# @param [::ActionDispatch::Request] original env.
|
77
|
+
# @return [::ActionDispatch::Request] a copy of original env with rails env merged.
|
76
78
|
def retrieve_request env
|
77
79
|
rails_env = ::Rails.application.env_config.merge(env)
|
78
80
|
::ActionDispatch::Request.new(rails_env || env)
|
@@ -87,37 +89,34 @@ module Contrast
|
|
87
89
|
|
88
90
|
private
|
89
91
|
|
90
|
-
# route is
|
91
|
-
|
92
|
-
|
93
|
-
|
92
|
+
# Determine if route is a Rails engine route.
|
93
|
+
#
|
94
|
+
# @param [Object] app or route that points to a ::Rails::Engine
|
95
|
+
# @return [bool] whether the router is an engine or not.
|
96
|
+
def engine_route? route
|
97
|
+
route.app.is_a?(::ActionDispatch::Routing::Mapper::Constraints) && route.app.app < ::Rails::Engine
|
94
98
|
end
|
95
99
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
# filter for current http method
|
117
|
-
reportable_routes = engine_router.send(:match_routes, matching_routes, request.rack_request)
|
118
|
-
return if reportable_routes.empty?
|
119
|
-
|
120
|
-
Contrast::Api::Dtm::RouteCoverage.from_action_dispatch_journey(reportable_routes[0])
|
100
|
+
# Recursively get final route traversing engines as required.
|
101
|
+
#
|
102
|
+
# @param request [::Rack::Request] the rack request as will be handed to rails controller.
|
103
|
+
# @param top_router [::ActionDispatch::Journer::Router] the current router relative to the previous.
|
104
|
+
# @param path [Array<String>] the chunks of path that have been seen.
|
105
|
+
# @return [Array<array>] the final set of rails route classes.
|
106
|
+
def get_full_route request, top_router = ::Rails.application.routes.router, path = []
|
107
|
+
return if (route_matches = top_router.send(:find_routes, request)).empty?
|
108
|
+
|
109
|
+
match, params, route = route_matches.first
|
110
|
+
|
111
|
+
# If the current routing node points to a sub-app (::Rais::Engine), dive deeper.
|
112
|
+
# Have sub-app route the remainder of the url.
|
113
|
+
if engine_route?(route)
|
114
|
+
new_req = retrieve_request request.env
|
115
|
+
new_req.path_info = new_req.path_info.gsub(match.to_s, '')
|
116
|
+
get_full_route(new_req, route.app.app.routes.router, path << match.to_s)
|
117
|
+
else
|
118
|
+
[match, params, route, path]
|
119
|
+
end
|
121
120
|
end
|
122
121
|
|
123
122
|
# Rails engine routes need to be detected by inspecting Engine class route set
|
@@ -1,8 +1,7 @@
|
|
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/framework/base_support'
|
5
|
-
require 'contrast/framework/sinatra/patch/support'
|
6
5
|
|
7
6
|
module Contrast
|
8
7
|
module Framework
|
@@ -10,7 +9,6 @@ module Contrast
|
|
10
9
|
# Used when Sinatra is present to define framework specific behavior
|
11
10
|
class Support
|
12
11
|
extend Contrast::Framework::BaseSupport
|
13
|
-
extend Contrast::Framework::Sinatra::Patch::Support
|
14
12
|
class << self
|
15
13
|
def detection_class
|
16
14
|
'Sinatra'
|
@@ -21,44 +19,74 @@ module Contrast
|
|
21
19
|
end
|
22
20
|
|
23
21
|
def application_name
|
24
|
-
|
25
|
-
|
26
|
-
app_class.cs__class.cs__name
|
22
|
+
app_class&.cs__name
|
27
23
|
end
|
28
24
|
|
29
25
|
def application_root
|
30
|
-
|
31
|
-
|
32
|
-
app_class.root
|
26
|
+
app_instance&.root
|
33
27
|
end
|
34
28
|
|
35
29
|
def server_type
|
36
30
|
'sinatra'
|
37
31
|
end
|
38
32
|
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
33
|
+
# Given an object, determine if it is a Sinatra controller with routes.
|
34
|
+
#
|
35
|
+
# @param app [Object] suspected Sinatra app.
|
36
|
+
# @return [Boolean]
|
37
|
+
def sinatra_controller? app
|
38
|
+
# Sinatra is loaded?
|
39
|
+
return false unless defined?(::Sinatra) && defined?(::Sinatra::Base)
|
40
|
+
# App is a subclass of or actually is ::Sinatra::Base.
|
41
|
+
return false unless (app.cs__respond_to?(:<) && app < ::Sinatra::Base) || app == ::Sinatra::Base
|
42
|
+
|
43
|
+
# App has routes.
|
44
|
+
!app.routes.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
# Find all classes that subclass ::Sinatra::Base. Gather their routes.
|
48
|
+
#
|
49
|
+
# @return [Array<Contrast::Api::Dtm::RouteCoverage>] the routes found as Dtms.
|
42
50
|
def collect_routes
|
51
|
+
return Contrast::Utils::ObjectShare::EMPTY_ARRAY unless defined?(::Sinatra) && defined?(::Sinatra::Base)
|
52
|
+
|
43
53
|
routes = []
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
class_routes.each_pair do |method, list|
|
50
|
-
# item: [ Mustermann::Sinatra, [], Proc]
|
51
|
-
list.each do |item|
|
52
|
-
routes << Contrast::Api::Dtm::RouteCoverage.from_sinatra_route(clazz, method, item[0])
|
54
|
+
sinatra_controllers.each do |controller|
|
55
|
+
controller.routes.each_pair do |method, route_triplets|
|
56
|
+
# Sinatra stores its routes as a triplet: [Mustermann::Sinatra, [], Proc]
|
57
|
+
route_triplets.map(&:first).each do |route_pattern|
|
58
|
+
routes << Contrast::Api::Dtm::RouteCoverage.from_sinatra_route(controller, method, route_pattern)
|
53
59
|
end
|
54
60
|
end
|
55
61
|
end
|
56
62
|
routes
|
57
63
|
end
|
58
64
|
|
59
|
-
#
|
60
|
-
|
61
|
-
|
65
|
+
# Given the current request return a RouteCoverage dtm.
|
66
|
+
#
|
67
|
+
# @param request [Contrast::Agent::Request] a contrast tracked request.
|
68
|
+
# @param controller [::Sinatra::Base] optionally use this controller instead of global ::Sinatra::Base.
|
69
|
+
# @return [Contrast::Api::Dtm::RouteCoverage, nil] a Dtm describing the route
|
70
|
+
# matched to the request if a match was found.
|
71
|
+
def current_route request, controller = ::Sinatra::Base, full_route = nil
|
72
|
+
return unless sinatra_controller?(controller)
|
73
|
+
|
74
|
+
method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
|
75
|
+
|
76
|
+
# Find route match--checking superclasses if necessary.
|
77
|
+
final_controller, route_pattern = _route_recurse(controller, method, _cleaned_route(request))
|
78
|
+
return unless !final_controller.nil? && !route_pattern.nil?
|
79
|
+
|
80
|
+
full_route ||= request.path_info
|
81
|
+
|
82
|
+
Contrast::Api::Dtm::RouteCoverage.from_sinatra_route(final_controller, method, route_pattern, full_route)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Search object space for sinatra controllers--any class that subclasses ::Sinatra::Base.
|
86
|
+
#
|
87
|
+
# @return [Array<::Sinatra::Base>] sinatra controlelrs
|
88
|
+
def sinatra_controllers
|
89
|
+
[::Sinatra::Base] + ObjectSpace.each_object(Class).select { |clazz| sinatra_controller?(clazz) }
|
62
90
|
end
|
63
91
|
|
64
92
|
def retrieve_request env
|
@@ -67,30 +95,61 @@ module Contrast
|
|
67
95
|
|
68
96
|
private
|
69
97
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
98
|
+
# Given a controller and a route to match against, find the route_pattern and class that will serve the
|
99
|
+
# route. This is recursive as Sinatra's routing is recursive from subclass to super.
|
100
|
+
#
|
101
|
+
# @param controller [Sinatra::Base, #routes] a Sinatra application.
|
102
|
+
# @param method [::Rack::REQUEST_METHOD] GET, POST, PUT, etc...
|
103
|
+
# @param method [String] the relative route passed from Rack.
|
104
|
+
# @return [Array[Sinatra::Base, Mustermann::Sinatra], nil] Either the controller that
|
105
|
+
# will handle the route along with the route pattern or nil if no match.
|
106
|
+
def _route_recurse controller, method, route
|
107
|
+
return if controller.nil? || controller.cs__class == NilClass
|
108
|
+
|
109
|
+
route_patterns = controller.routes.fetch(method, []).map(&:first)
|
110
|
+
route_pattern = route_patterns&.find do |matcher|
|
111
|
+
matcher.params(route) # ::Mustermann::Sinatra match.
|
77
112
|
end
|
113
|
+
|
114
|
+
return controller, route_pattern if route_pattern
|
115
|
+
|
116
|
+
# Check routes defined in superclass if present.
|
117
|
+
return _route_recurse(controller.superclass, method, route) if controller.superclass&.instance_variable_get(:@routes)
|
78
118
|
end
|
79
119
|
|
80
|
-
#
|
81
|
-
#
|
82
|
-
# Contrast::
|
83
|
-
|
84
|
-
|
120
|
+
# Get route and do some cleanup matching that of Sinatra::Base#process_route.
|
121
|
+
#
|
122
|
+
# @param request [Contrast::Agent::Request] a contrast tracked request.
|
123
|
+
# @return [String] the extracted and cleaned relative route.
|
124
|
+
def _cleaned_route request
|
125
|
+
settings = ::Sinatra::Base.settings
|
126
|
+
route = request.env[::Rack::PATH_INFO]
|
127
|
+
return '/' if route.empty? && !settings.empty_path_info?
|
128
|
+
|
129
|
+
!settings.strict_paths? && route.end_with?('/') ? route[0..-2] : route
|
130
|
+
end
|
85
131
|
|
86
|
-
|
132
|
+
# Almost an alias to app_instance.
|
133
|
+
#
|
134
|
+
# @return [::Sinatra::Base] the current controller class as routed by Rack.
|
135
|
+
def app_class
|
136
|
+
return unless defined?(::Sinatra) && defined?(::Sinatra::Base)
|
137
|
+
|
138
|
+
app_instance.cs__class
|
87
139
|
end
|
88
140
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
141
|
+
# Search the object space for the controller handling this request which will be
|
142
|
+
# the class inheriting from ::Sinatra::Base with @app=nil since it is the final servicer
|
143
|
+
# in the request/middleware chain.
|
144
|
+
#
|
145
|
+
# @return [::Sinatra::Base] the current controller as routed by Rack.
|
146
|
+
def app_instance
|
147
|
+
return unless defined?(::Sinatra) && defined?(::Sinatra::Base)
|
148
|
+
|
149
|
+
@_app_instance ||= begin
|
150
|
+
sinatra_layers = ObjectSpace.each_object(::Sinatra::Base).to_a
|
151
|
+
sinatra_layers.find { |layer| layer.app.nil? }
|
152
|
+
end
|
94
153
|
end
|
95
154
|
end
|
96
155
|
end
|