contrast-agent 6.6.4 → 6.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -2
- data/.gitmodules +0 -3
- data/.simplecov +0 -1
- data/Rakefile +0 -1
- data/ext/cs__assess_array/cs__assess_array.c +41 -10
- data/ext/cs__assess_array/cs__assess_array.h +4 -1
- data/ext/cs__scope/cs__scope.c +1 -1
- data/lib/contrast/agent/assess/contrast_event.rb +2 -24
- data/lib/contrast/agent/assess/events/source_event.rb +7 -61
- data/lib/contrast/agent/assess/finalizers/hash.rb +11 -0
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +0 -55
- data/lib/contrast/agent/assess/policy/policy_node.rb +3 -3
- data/lib/contrast/agent/assess/policy/policy_node_utils.rb +0 -1
- data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
- data/lib/contrast/agent/assess/policy/source_method.rb +24 -1
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -5
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +6 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +40 -121
- data/lib/contrast/agent/assess/policy/trigger_node.rb +3 -3
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -1
- data/lib/contrast/agent/assess/property/evented.rb +2 -12
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +42 -82
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +11 -27
- data/lib/contrast/agent/assess/rule/response/body_rule.rb +1 -3
- data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +77 -62
- data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +6 -1
- data/lib/contrast/agent/assess/rule/response/header_rule.rb +5 -5
- data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +1 -1
- data/lib/contrast/agent/assess/tracker.rb +1 -7
- data/lib/contrast/agent/at_exit_hook.rb +1 -7
- data/lib/contrast/agent/excluder.rb +224 -0
- data/lib/contrast/agent/exclusion_matcher.rb +25 -7
- data/lib/contrast/agent/inventory/database_config.rb +18 -23
- data/lib/contrast/agent/middleware.rb +4 -5
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +6 -0
- data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +146 -127
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +4 -0
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +20 -0
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -0
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +1 -1
- data/lib/contrast/agent/protect/rule/base.rb +98 -66
- data/lib/contrast/agent/protect/rule/base_service.rb +49 -24
- data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +98 -0
- data/lib/contrast/agent/protect/rule/bot_blocker.rb +81 -0
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +30 -99
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +132 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +169 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +69 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +68 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +2 -58
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +10 -19
- data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +2 -2
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +0 -11
- data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +29 -34
- data/lib/contrast/agent/protect/rule/no_sqli.rb +25 -18
- data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_input_classification.rb +61 -0
- data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +114 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +46 -18
- data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +49 -29
- data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +37 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +2 -62
- data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +67 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +67 -22
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +39 -63
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +6 -33
- data/lib/contrast/agent/protect/rule/xss/reflected_xss_input_classification.rb +58 -0
- data/lib/contrast/agent/protect/rule/xss.rb +14 -20
- data/lib/contrast/agent/protect/rule/xxe.rb +15 -30
- data/lib/contrast/agent/protect/rule.rb +3 -1
- data/lib/contrast/agent/reporting/attack_result/attack_result.rb +8 -0
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +70 -36
- data/lib/contrast/agent/reporting/attack_result/response_type.rb +9 -9
- data/lib/contrast/agent/reporting/attack_result/user_input.rb +11 -0
- data/lib/contrast/agent/reporting/details/bot_blocker_details.rb +29 -0
- data/lib/contrast/agent/reporting/details/cmd_injection_details.rb +30 -0
- data/lib/contrast/agent/reporting/details/details.rb +18 -0
- data/lib/contrast/agent/reporting/details/http_method_tempering_details.rb +27 -0
- data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +35 -0
- data/lib/contrast/agent/reporting/details/no_sqli_details.rb +36 -0
- data/lib/contrast/agent/reporting/details/path_traversal_details.rb +24 -0
- data/lib/contrast/agent/reporting/details/path_traversal_semantic_analysis_details.rb +32 -0
- data/lib/contrast/agent/reporting/details/protect_rule_details.rb +17 -0
- data/lib/contrast/agent/reporting/details/sqli_dangerous_functions.rb +22 -0
- data/lib/contrast/agent/reporting/details/sqli_details.rb +36 -0
- data/lib/contrast/agent/reporting/details/untrusted_deserialization_details.rb +27 -0
- data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +30 -0
- data/lib/contrast/agent/reporting/details/xss_details.rb +33 -0
- data/lib/contrast/agent/reporting/details/xss_match.rb +30 -0
- data/lib/contrast/agent/reporting/details/xxe_details.rb +36 -0
- data/lib/contrast/agent/reporting/details/xxe_match.rb +25 -0
- data/lib/contrast/agent/reporting/details/xxe_wrapper.rb +25 -0
- data/lib/contrast/agent/reporting/input_analysis/details/bot_blocker_details.rb +27 -0
- data/lib/contrast/agent/reporting/input_analysis/details/protect_rule_details.rb +15 -0
- data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +1 -2
- data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +17 -3
- data/lib/contrast/agent/reporting/masker/masker.rb +80 -65
- data/lib/contrast/agent/reporting/masker/masker_utils.rb +1 -30
- data/lib/contrast/agent/reporting/reporter.rb +1 -15
- data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +84 -15
- data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +13 -25
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +19 -24
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +46 -126
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +5 -16
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +10 -18
- data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -14
- data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/application_update.rb +0 -2
- data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +7 -22
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +23 -53
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +12 -9
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +23 -21
- data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +5 -18
- data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +1 -0
- data/lib/contrast/{api/decorators/trace_taint_range_tags.rb → agent/reporting/reporting_events/finding_event_taint_range_tags.rb} +7 -6
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +40 -10
- data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_events/poll.rb +1 -11
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -14
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +11 -0
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +3 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +12 -25
- data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +8 -27
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +3 -3
- data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +4 -7
- data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +3 -3
- data/lib/contrast/agent/reporting/reporting_utilities/response.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +0 -3
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -0
- data/lib/contrast/agent/reporting/settings/code_exclusion.rb +6 -1
- data/lib/contrast/agent/reporting/settings/exclusion_base.rb +18 -0
- data/lib/contrast/agent/reporting/settings/exclusions.rb +2 -1
- data/lib/contrast/agent/reporting/settings/input_exclusion.rb +9 -3
- data/lib/contrast/agent/reporting/settings/protect.rb +15 -15
- data/lib/contrast/agent/request.rb +4 -14
- data/lib/contrast/agent/request_context.rb +18 -24
- data/lib/contrast/agent/request_context_extend.rb +23 -164
- data/lib/contrast/agent/request_handler.rb +1 -11
- data/lib/contrast/agent/response.rb +0 -18
- data/lib/contrast/agent/telemetry/events/event.rb +1 -1
- data/lib/contrast/agent/telemetry/events/metric_event.rb +1 -1
- data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +3 -3
- data/lib/contrast/agent/thread_watcher.rb +3 -18
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +0 -11
- data/lib/contrast/agent_lib/api/command_injection.rb +46 -0
- data/lib/contrast/agent_lib/api/init.rb +101 -0
- data/lib/contrast/agent_lib/api/input_tracing.rb +267 -0
- data/lib/contrast/agent_lib/api/method_tempering.rb +29 -0
- data/lib/contrast/agent_lib/api/panic.rb +87 -0
- data/lib/contrast/agent_lib/api/path_semantic_file_security_bypass.rb +40 -0
- data/lib/contrast/agent_lib/interface.rb +260 -0
- data/lib/contrast/agent_lib/interface_base.rb +118 -0
- data/lib/contrast/agent_lib/return_types/eval_result.rb +44 -0
- data/lib/contrast/agent_lib/test.rb +29 -0
- data/lib/contrast/api/communication/connection_status.rb +5 -5
- data/lib/contrast/components/agent.rb +13 -23
- data/lib/contrast/components/api.rb +10 -10
- data/lib/contrast/components/app_context.rb +9 -11
- data/lib/contrast/components/app_context_extend.rb +1 -26
- data/lib/contrast/components/assess.rb +92 -38
- data/lib/contrast/components/assess_rules.rb +36 -0
- data/lib/contrast/components/config.rb +49 -24
- data/lib/contrast/components/heap_dump.rb +1 -1
- data/lib/contrast/components/protect.rb +9 -6
- data/lib/contrast/components/ruby_component.rb +81 -0
- data/lib/contrast/components/sampling.rb +1 -1
- data/lib/contrast/components/security_logger.rb +23 -0
- data/lib/contrast/components/settings.rb +41 -85
- data/lib/contrast/config/base_configuration.rb +1 -1
- data/lib/contrast/config/protect_rule_configuration.rb +7 -7
- data/lib/contrast/config/protect_rules_configuration.rb +24 -48
- data/lib/contrast/config/server_configuration.rb +1 -1
- data/lib/contrast/config.rb +0 -6
- data/lib/contrast/configuration.rb +73 -18
- data/lib/contrast/extension/assess/array.rb +9 -0
- data/lib/contrast/extension/assess/exec_trigger.rb +3 -1
- data/lib/contrast/extension/assess/marshal.rb +3 -2
- data/lib/contrast/extension/assess/string.rb +0 -1
- data/lib/contrast/extension/delegator.rb +2 -0
- data/lib/contrast/extension/extension.rb +1 -1
- data/lib/contrast/framework/base_support.rb +0 -5
- data/lib/contrast/framework/grape/support.rb +1 -23
- data/lib/contrast/framework/manager.rb +3 -11
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -6
- data/lib/contrast/framework/rails/railtie.rb +0 -1
- data/lib/contrast/framework/rails/support.rb +5 -59
- data/lib/contrast/framework/sinatra/support.rb +2 -21
- data/lib/contrast/logger/cef_log.rb +21 -3
- data/lib/contrast/logger/log.rb +1 -11
- data/lib/contrast/tasks/config.rb +5 -10
- data/lib/contrast/utils/assess/event_limit_utils.rb +28 -12
- data/lib/contrast/utils/assess/trigger_method_utils.rb +10 -18
- data/lib/contrast/utils/duck_utils.rb +1 -0
- data/lib/contrast/utils/findings.rb +6 -5
- data/lib/contrast/utils/hash_digest.rb +9 -24
- data/lib/contrast/utils/hash_digest_extend.rb +6 -6
- data/lib/contrast/utils/input_classification_base.rb +156 -0
- data/lib/contrast/utils/invalid_configuration_util.rb +21 -58
- data/lib/contrast/utils/log_utils.rb +47 -17
- data/lib/contrast/utils/net_http_base.rb +2 -2
- data/lib/contrast/utils/os.rb +0 -20
- data/lib/contrast/utils/patching/policy/patch_utils.rb +3 -2
- data/lib/contrast/utils/response_utils.rb +0 -16
- data/lib/contrast/utils/stack_trace_utils.rb +3 -40
- data/lib/contrast/utils/string_utils.rb +19 -7
- data/lib/contrast/utils/telemetry_client.rb +13 -7
- data/lib/contrast.rb +7 -13
- data/resources/protect/policy.json +1 -2
- data/ruby-agent.gemspec +2 -5
- metadata +78 -137
- data/exe/contrast_service +0 -23
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +0 -64
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +0 -118
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +0 -45
- data/lib/contrast/agent/reaction_processor.rb +0 -47
- data/lib/contrast/agent/reporting/reporting_events/trace_event_source.rb +0 -30
- data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -43
- data/lib/contrast/agent/service_heartbeat.rb +0 -35
- data/lib/contrast/api/communication/messaging_queue.rb +0 -129
- data/lib/contrast/api/communication/response_processor.rb +0 -90
- data/lib/contrast/api/communication/service_lifecycle.rb +0 -77
- data/lib/contrast/api/communication/socket.rb +0 -44
- data/lib/contrast/api/communication/socket_client.rb +0 -130
- data/lib/contrast/api/communication/speedracer.rb +0 -142
- data/lib/contrast/api/communication/tcp_socket.rb +0 -32
- data/lib/contrast/api/communication/unix_socket.rb +0 -28
- data/lib/contrast/api/communication.rb +0 -20
- data/lib/contrast/api/decorators/activity.rb +0 -33
- data/lib/contrast/api/decorators/address.rb +0 -59
- data/lib/contrast/api/decorators/agent_startup.rb +0 -57
- data/lib/contrast/api/decorators/application_settings.rb +0 -42
- data/lib/contrast/api/decorators/application_startup.rb +0 -56
- data/lib/contrast/api/decorators/architecture_component.rb +0 -36
- data/lib/contrast/api/decorators/bot_blocker.rb +0 -37
- data/lib/contrast/api/decorators/finding.rb +0 -29
- data/lib/contrast/api/decorators/http_request.rb +0 -137
- data/lib/contrast/api/decorators/input_analysis.rb +0 -18
- data/lib/contrast/api/decorators/instrumentation_mode.rb +0 -35
- data/lib/contrast/api/decorators/ip_denylist.rb +0 -37
- data/lib/contrast/api/decorators/message.rb +0 -71
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -58
- data/lib/contrast/api/decorators/response_type.rb +0 -17
- data/lib/contrast/api/decorators/route_coverage.rb +0 -91
- data/lib/contrast/api/decorators/server_features.rb +0 -25
- data/lib/contrast/api/decorators/trace_event.rb +0 -120
- data/lib/contrast/api/decorators/trace_event_object.rb +0 -63
- data/lib/contrast/api/decorators/trace_event_signature.rb +0 -69
- data/lib/contrast/api/decorators/trace_taint_range.rb +0 -52
- data/lib/contrast/api/decorators/user_input.rb +0 -51
- data/lib/contrast/api/decorators/virtual_patch.rb +0 -34
- data/lib/contrast/api/decorators.rb +0 -28
- data/lib/contrast/api/dtm.pb.rb +0 -852
- data/lib/contrast/api/settings.pb.rb +0 -500
- data/lib/contrast/api.rb +0 -16
- data/lib/contrast/components/contrast_service.rb +0 -88
- data/lib/contrast/config/assess_configuration.rb +0 -93
- data/lib/contrast/config/assess_rules_configuration.rb +0 -32
- data/lib/contrast/config/root_configuration.rb +0 -90
- data/lib/contrast/config/ruby_configuration.rb +0 -81
- data/lib/contrast/config/service_configuration.rb +0 -49
- data/lib/contrast/tasks/service.rb +0 -84
- data/lib/contrast/utils/input_classification.rb +0 -73
- data/lib/contrast/utils/preflight_util.rb +0 -13
- data/lib/protobuf/code_generator.rb +0 -129
- data/lib/protobuf/decoder.rb +0 -28
- data/lib/protobuf/deprecation.rb +0 -117
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +0 -79
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +0 -360
- data/lib/protobuf/descriptors.rb +0 -3
- data/lib/protobuf/encoder.rb +0 -11
- data/lib/protobuf/enum.rb +0 -365
- data/lib/protobuf/exceptions.rb +0 -9
- data/lib/protobuf/field/base_field.rb +0 -380
- data/lib/protobuf/field/base_field_object_definitions.rb +0 -504
- data/lib/protobuf/field/bool_field.rb +0 -64
- data/lib/protobuf/field/bytes_field.rb +0 -67
- data/lib/protobuf/field/double_field.rb +0 -25
- data/lib/protobuf/field/enum_field.rb +0 -56
- data/lib/protobuf/field/field_array.rb +0 -102
- data/lib/protobuf/field/field_hash.rb +0 -122
- data/lib/protobuf/field/fixed32_field.rb +0 -25
- data/lib/protobuf/field/fixed64_field.rb +0 -28
- data/lib/protobuf/field/float_field.rb +0 -43
- data/lib/protobuf/field/int32_field.rb +0 -21
- data/lib/protobuf/field/int64_field.rb +0 -34
- data/lib/protobuf/field/integer_field.rb +0 -23
- data/lib/protobuf/field/message_field.rb +0 -51
- data/lib/protobuf/field/sfixed32_field.rb +0 -27
- data/lib/protobuf/field/sfixed64_field.rb +0 -28
- data/lib/protobuf/field/signed_integer_field.rb +0 -29
- data/lib/protobuf/field/sint32_field.rb +0 -21
- data/lib/protobuf/field/sint64_field.rb +0 -21
- data/lib/protobuf/field/string_field.rb +0 -51
- data/lib/protobuf/field/uint32_field.rb +0 -21
- data/lib/protobuf/field/uint64_field.rb +0 -21
- data/lib/protobuf/field/varint_field.rb +0 -77
- data/lib/protobuf/field.rb +0 -74
- data/lib/protobuf/generators/base.rb +0 -85
- data/lib/protobuf/generators/enum_generator.rb +0 -39
- data/lib/protobuf/generators/extension_generator.rb +0 -27
- data/lib/protobuf/generators/field_generator.rb +0 -193
- data/lib/protobuf/generators/file_generator.rb +0 -262
- data/lib/protobuf/generators/group_generator.rb +0 -122
- data/lib/protobuf/generators/message_generator.rb +0 -104
- data/lib/protobuf/generators/option_generator.rb +0 -17
- data/lib/protobuf/generators/printable.rb +0 -160
- data/lib/protobuf/generators/service_generator.rb +0 -50
- data/lib/protobuf/lifecycle.rb +0 -33
- data/lib/protobuf/logging.rb +0 -39
- data/lib/protobuf/message/fields.rb +0 -233
- data/lib/protobuf/message/serialization.rb +0 -85
- data/lib/protobuf/message.rb +0 -241
- data/lib/protobuf/optionable.rb +0 -72
- data/lib/protobuf/tasks/compile.rake +0 -80
- data/lib/protobuf/tasks.rb +0 -1
- data/lib/protobuf/varint.rb +0 -20
- data/lib/protobuf/varint_pure.rb +0 -31
- data/lib/protobuf/version.rb +0 -3
- data/lib/protobuf/wire_type.rb +0 -10
- data/lib/protobuf.rb +0 -91
- data/proto/dynamic_discovery.proto +0 -46
- data/proto/google/protobuf/compiler/plugin.proto +0 -183
- data/proto/google/protobuf/descriptor.proto +0 -911
- data/proto/rpc.proto +0 -71
- data/service_executables/.gitkeep +0 -0
- data/service_executables/VERSION +0 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'contrast/agent/assess/rule/response/header_rule'
|
5
5
|
require 'contrast/agent/assess/rule/response/body_rule'
|
6
|
-
require 'contrast/
|
6
|
+
require 'contrast/utils/object_share'
|
7
7
|
require 'contrast/utils/string_utils'
|
8
8
|
require 'json'
|
9
9
|
|
@@ -16,7 +16,6 @@ module Contrast
|
|
16
16
|
# set incorrectly the cache-control header
|
17
17
|
class CacheControl < HeaderRule
|
18
18
|
include BodyRule
|
19
|
-
include Framework::RailsSupport
|
20
19
|
HEADER_KEYS = %w[Cache-Control].cs__freeze
|
21
20
|
ACCEPTED_VALUES = [/no-store/, /no-cache/].cs__freeze
|
22
21
|
DEFAULT_SAFE = false
|
@@ -33,66 +32,65 @@ module Contrast
|
|
33
32
|
# Determine if the Response violates the Rule or not. If it does, return the evidence that proves it so.
|
34
33
|
#
|
35
34
|
# @param response [Contrast::Agent::Response] the response of the application
|
36
|
-
# @return [Hash, nil] the evidence required to prove the violation of
|
35
|
+
# @return [Hash<String,Array<Hash<String,String>>>, nil] the evidence required to prove the violation of
|
36
|
+
# the rule
|
37
37
|
def violated? response
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
38
|
+
cache_header = cache_control_from(response)
|
39
|
+
cache_meta = cache_meta_tags(response)
|
40
|
+
|
41
|
+
has_header = cache_header && !cache_header.blank?
|
42
|
+
has_meta = cache_meta.any?
|
43
|
+
# Because we're not safe by default, the rule should never hit this case, but we'll handle it just in
|
44
|
+
# case.
|
45
|
+
return { DATA => Contrast::Utils::ObjectShare::EMPTY_ARRAY.to_json } unless has_header || has_meta
|
46
|
+
|
47
|
+
evidence = []
|
48
|
+
# If we have a header tag, then we need to make sure it is set safely. If it is, there'll be no evidence
|
49
|
+
# and we can return as the header prevents violation.
|
50
|
+
if has_header
|
51
|
+
header_evidence = header_evidence(cache_header)
|
52
|
+
return unless header_evidence
|
53
|
+
|
54
|
+
evidence << header_evidence
|
55
|
+
end
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
# If we have no header, or an unsafe header, then we need to check the meta tag to make sure it is set
|
58
|
+
# safely. If it is, there'll be no evidence and we can return as the meta tag prevents violation.
|
59
|
+
if has_meta
|
60
|
+
tag_evidence = tag_evidence(cache_meta)
|
61
|
+
return unless tag_evidence
|
62
62
|
|
63
|
-
|
64
|
-
return true if meta_cache_tag?(tag[HTML_PROP])
|
63
|
+
evidence << tag_evidence
|
65
64
|
end
|
66
65
|
|
67
|
-
|
66
|
+
# Otherwise, we'll report the violation.
|
67
|
+
{ DATA => evidence.to_json }
|
68
68
|
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
# @param response [Contrast::Agent::Response] the response of the application
|
71
|
+
# @return [Array<Hash<String,String>]
|
72
|
+
def cache_meta_tags response
|
73
|
+
html_elements(response.body&.split(HEAD_TAG)&.last, META_START_STR).
|
74
|
+
select { |tag| cache_control_tag?(tag[HTML_PROP]) }
|
74
75
|
end
|
75
76
|
|
76
77
|
# Process Header value to determine if it violates rule
|
77
|
-
# @param
|
78
|
-
# @return [Hash, nil] the evidence hash or nil
|
79
|
-
def header_evidence
|
80
|
-
cache_control = cache_control_from(response)
|
81
|
-
value = framework_supported? ? cache_control : cache_control_to_s(cache_control)
|
78
|
+
# @param cache_control [String] the value of the Cache-Control header
|
79
|
+
# @return [Hash<String,String>, nil] the evidence hash or nil
|
80
|
+
def header_evidence cache_control
|
82
81
|
# If header is valid, then this portion of the rule isn't violated.
|
83
|
-
return if valid_header?(
|
82
|
+
return if valid_header?(cache_control)
|
84
83
|
|
85
84
|
# evidence requires header value string, pull directly instead of rebuilding from hash
|
86
|
-
evidence(HEADER_TYPE, NAME,
|
85
|
+
evidence(HEADER_TYPE, NAME, cache_control)
|
87
86
|
end
|
88
87
|
|
89
88
|
# Process Body to determine if cache control meta tag violates rule
|
90
|
-
# @param
|
91
|
-
# @return [Hash, nil] the evidence hash or nil
|
92
|
-
def tag_evidence
|
93
|
-
|
94
|
-
|
95
|
-
end
|
89
|
+
# @param cache_meta_tags [Array<Hash>] the meta tags which contain Cache-Control values
|
90
|
+
# @return [Hash<String,String>, nil] the evidence hash or nil
|
91
|
+
def tag_evidence cache_meta_tags
|
92
|
+
violation = cache_meta_tags.find { |tag| !safe_meta_cache_tag?(tag[HTML_PROP]) }
|
93
|
+
violation ? evidence(META_TYPE, PRAGMA, violation[HTML_PROP]) : nil
|
96
94
|
end
|
97
95
|
|
98
96
|
def potential_elements section, element_start
|
@@ -107,13 +105,27 @@ module Contrast
|
|
107
105
|
[/'no-cache'/i, /"no-cache"/i, /"no-store"/i, /'no-store'/i, /'cache-control'/i, /"cache-control"/i]
|
108
106
|
end
|
109
107
|
|
108
|
+
# @param tag [String] the tag to check
|
109
|
+
# @return [Boolean] if the tag has cache-control settings or not
|
110
|
+
def cache_control_tag? tag
|
111
|
+
http_equiv_idx = tag =~ /http-equiv=/i
|
112
|
+
return false unless http_equiv_idx
|
113
|
+
|
114
|
+
content_idx = tag =~ /content=/i
|
115
|
+
return false unless content_idx
|
116
|
+
|
117
|
+
# determine the value of the http-equiv if it's cache-control
|
118
|
+
http_equiv_idx += 11
|
119
|
+
accepted_http_values.any? { |el| (tag =~ el) == http_equiv_idx }
|
120
|
+
end
|
121
|
+
|
110
122
|
# Determine if the given metatag does not have a valid cache-control tag.
|
111
123
|
# Meta tags has the option to set http-equiv and content to set the http response header
|
112
124
|
# to define for the document
|
113
125
|
#
|
114
126
|
# @param tag [String] the meta tag
|
115
127
|
# @return [Boolean, nil]
|
116
|
-
def
|
128
|
+
def safe_meta_cache_tag? tag
|
117
129
|
# Here we should determine the index of the needed keys
|
118
130
|
# http-equiv and content
|
119
131
|
http_equiv_idx = tag =~ /http-equiv=/i
|
@@ -128,33 +140,36 @@ module Contrast
|
|
128
140
|
return false unless is_valid
|
129
141
|
|
130
142
|
content_idx += 8
|
131
|
-
|
132
|
-
|
133
|
-
true
|
143
|
+
accepted_values.any? { |value| (tag =~ value) == content_idx }
|
134
144
|
end
|
135
145
|
|
136
|
-
# This method accepts the violation and transforms it to the proper hash
|
137
|
-
#
|
146
|
+
# This method accepts the violation and transforms it to the proper hash before returning a violation.
|
147
|
+
# Unlike other rules, this returns a complex structure to be converted to JSON on reporting -- do NOT cast
|
148
|
+
# it here as that'll result in extra escaping later.
|
138
149
|
#
|
139
150
|
# @param type [String] String of Header or META of the type
|
140
151
|
# @param name [String] String of either cache-control or pragma
|
141
152
|
# @param value [String] String of the violated value
|
153
|
+
# @return [Hash<String, String>]
|
142
154
|
def evidence type, name, value
|
143
|
-
{ type
|
155
|
+
{ 'type' => type, 'name' => name, 'value' => value }
|
144
156
|
end
|
145
157
|
|
158
|
+
# return the cache control value from the response, either as a Hash in later versions of Rails or as a
|
159
|
+
# String in all other frameworks/ response types (remember, response can be a few things).
|
160
|
+
#
|
161
|
+
# @param response [Contrast::Agent::Response]
|
162
|
+
# @return [String]
|
146
163
|
def cache_control_from response
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
164
|
+
control = if response.rack_response.cs__is_a?(Rack::Response)
|
165
|
+
response.rack_response.cache_control
|
166
|
+
else
|
167
|
+
get_header_value(response)
|
168
|
+
end
|
169
|
+
control.cs__is_a?(Hash) ? cache_control_to_s(control) : control
|
154
170
|
end
|
155
171
|
|
156
|
-
# Rebuilds the String value of the Cache-Control Header
|
157
|
-
# from the hash build in the Rack::Response
|
172
|
+
# Rebuilds the String value of the Cache-Control Header from the hash build in the Rack::Response
|
158
173
|
#
|
159
174
|
# @param hsh [Hash]
|
160
175
|
# @return [String]
|
@@ -46,7 +46,7 @@ module Contrast
|
|
46
46
|
settings["#{ key }Secure"] = !value.nil? && value_secure?(value) && value_safe?(value)
|
47
47
|
settings["#{ key }Value"] = value.nil? ? Contrast::Utils::ObjectShare::EMPTY_STRING : value
|
48
48
|
end
|
49
|
-
evidence(settings) if settings.value?(false)
|
49
|
+
evidence(settings.to_json) if settings.value?(false)
|
50
50
|
end
|
51
51
|
|
52
52
|
# Get the CSP values from and transforms them to key value hash
|
@@ -12,7 +12,12 @@ module Contrast
|
|
12
12
|
module RailsSupport
|
13
13
|
RAILS_VERSION = Gem::Version.new('7.0.0')
|
14
14
|
|
15
|
-
|
15
|
+
# Some rules have features or settings that make them unsupported, meaning unnecessary or unavailable
|
16
|
+
# in that framework. For now, the only distinction required is Rails 7 or not, so that's what we'll
|
17
|
+
# report here.
|
18
|
+
#
|
19
|
+
# @return [Boolean] if the rule is unsupported by the framework
|
20
|
+
def rails_seven?
|
16
21
|
return false unless defined?(::Rails)
|
17
22
|
|
18
23
|
rails_version = ::Rails.version
|
@@ -2,9 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'rack'
|
5
|
-
require 'contrast/agent/reporting/reporting_utilities/dtm_message'
|
6
5
|
require 'contrast/utils/hash_digest'
|
7
|
-
require 'contrast/utils/preflight_util'
|
8
6
|
require 'contrast/utils/string_utils'
|
9
7
|
require 'contrast/agent/assess/rule/response/base_rule'
|
10
8
|
|
@@ -16,7 +14,7 @@ module Contrast
|
|
16
14
|
# These rules check the content of the HTTP Response to determine if something was set incorrectly or
|
17
15
|
# insecurely in it.
|
18
16
|
class HeaderRule < BaseRule
|
19
|
-
HEADER_TYPE = '
|
17
|
+
HEADER_TYPE = 'Header'
|
20
18
|
|
21
19
|
# Rules discern which responses they can/should analyze.
|
22
20
|
#
|
@@ -44,11 +42,13 @@ module Contrast
|
|
44
42
|
# @param response [Contrast::Agent::Response] the response of the application
|
45
43
|
# @return [Boolean]
|
46
44
|
def headers? response
|
47
|
-
response.headers&.any?
|
45
|
+
!!response.headers&.any?
|
48
46
|
end
|
49
47
|
|
50
48
|
protected
|
51
49
|
|
50
|
+
# @param response [Contrast::Agent::Response]
|
51
|
+
# @return [Object]
|
52
52
|
def get_header_value response
|
53
53
|
response_headers = response.headers
|
54
54
|
values = response_headers.values_at(*cs__class::HEADER_KEYS, *cs__class::HEADER_KEYS.map(&:to_sym))
|
@@ -57,7 +57,7 @@ module Contrast
|
|
57
57
|
|
58
58
|
# Determine if the value of the Response Header has a valid value
|
59
59
|
#
|
60
|
-
# @param header [
|
60
|
+
# @param header [String] a response header
|
61
61
|
# @return [Boolean] whether the header value is valid
|
62
62
|
def valid_header? header
|
63
63
|
cs__class::ACCEPTED_VALUES.any? { |val| val.match(header) }
|
@@ -12,7 +12,6 @@ module Contrast
|
|
12
12
|
# have tightly coupled dependencies on each other.
|
13
13
|
class Tracker
|
14
14
|
PROPERTIES_HASH = Contrast::Agent::Assess::Finalizers::Hash.new
|
15
|
-
KEEP_AGE = 600_000.cs__freeze # 10 minutes
|
16
15
|
|
17
16
|
class << self
|
18
17
|
# Retrieve the properties of the given Object, iff they exist.
|
@@ -60,12 +59,7 @@ module Contrast
|
|
60
59
|
# Clean PROPERTIES_HASH of any values older than KEEP_AGE ms or
|
61
60
|
# have nil properties
|
62
61
|
def cleanup!
|
63
|
-
PROPERTIES_HASH.
|
64
|
-
return true if properties.nil?
|
65
|
-
return false unless (event = properties&.event)
|
66
|
-
|
67
|
-
KEEP_AGE <= (Contrast::Utils::Timer.now_ms - event.time)
|
68
|
-
end
|
62
|
+
PROPERTIES_HASH.cleanup!
|
69
63
|
end
|
70
64
|
end
|
71
65
|
end
|
@@ -37,13 +37,7 @@ module Contrast
|
|
37
37
|
].compact.each do |event|
|
38
38
|
Contrast::Agent.reporter&.send_event_immediately(event)
|
39
39
|
end
|
40
|
-
|
41
|
-
if Contrast::Agent::Reporter.enabled?
|
42
|
-
event = Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity)
|
43
|
-
Contrast::Agent.reporter&.send_event_immediately(event)
|
44
|
-
else
|
45
|
-
Contrast::Agent.messaging_queue&.send_event_immediately(context.activity)
|
46
|
-
end
|
40
|
+
Contrast::Agent.reporter&.send_event_immediately(context.activity)
|
47
41
|
end
|
48
42
|
end
|
49
43
|
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/agent/reporting/settings/url_exclusion'
|
5
|
+
|
6
|
+
module Contrast
|
7
|
+
module Agent
|
8
|
+
# Given an array of exclusion matcher instances provides methods to
|
9
|
+
# determine if the exclusions apply to particular urls.
|
10
|
+
class Excluder # rubocop:disable Metrics/ClassLength
|
11
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
12
|
+
attr_reader :exclusions
|
13
|
+
|
14
|
+
# @param exclusions [Array<Contrast::Agent::ExclusionMatcher>]
|
15
|
+
def initialize exclusions = []
|
16
|
+
@exclusions = exclusions
|
17
|
+
end
|
18
|
+
|
19
|
+
# If an assess URL exclusion rule applies to the current url, *and* is defined as "All Rules"
|
20
|
+
# then we can avoid any tracking for the request.
|
21
|
+
#
|
22
|
+
# @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
|
23
|
+
# @return [Boolean]
|
24
|
+
def assess_excluded_by_url? request
|
25
|
+
request_path = request.path
|
26
|
+
|
27
|
+
assess_url_exclusions_for_all_rules.any? do |exclusion_matcher|
|
28
|
+
path_match?(exclusion_matcher, request_path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# If an assess URL exclusion rule applies to the current url, *and* also covers the
|
33
|
+
# provided rule_id, then we can avoid tracking this entry.
|
34
|
+
#
|
35
|
+
# @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
|
36
|
+
# @param rule_id [String]
|
37
|
+
# return [Boolean]
|
38
|
+
def assess_excluded_by_url_and_rule? request, rule_id
|
39
|
+
request_path = request.path
|
40
|
+
|
41
|
+
assess_url_exclusions.any? do |exclusion_matcher|
|
42
|
+
path_match?(exclusion_matcher, request_path) &&
|
43
|
+
(exclusion_matcher.assess_rules.empty? || exclusion_matcher.assess_rules.include?(rule_id))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# If an assess INPUT exclusion rule applies to the current url, *and* also covers all
|
48
|
+
# rules, then we can avoid tracking this entry.
|
49
|
+
#
|
50
|
+
# @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
|
51
|
+
# @param source_type [String]
|
52
|
+
# @param source_name [String]
|
53
|
+
# return [Boolean]
|
54
|
+
def assess_excluded_by_input? request, source_type, source_name
|
55
|
+
request_path = request.path
|
56
|
+
|
57
|
+
assess_input_exclusions_for_all_rules.any? do |exclusion_matcher|
|
58
|
+
input_match?(exclusion_matcher, source_type, source_name) && path_match?(exclusion_matcher, request_path)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# If an assess INPUT exclusion rule covers the provided rule_id *for all finding event sources*, then we
|
63
|
+
# can avoid tracking this entry. If any event source *isn't excluded* then we don't exclude the finding.
|
64
|
+
#
|
65
|
+
# @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
|
66
|
+
# @param finding [Contrast::Agent::Reporting::Finding]
|
67
|
+
# @param rule [String]
|
68
|
+
# return [Boolean]
|
69
|
+
def assess_excluded_by_input_and_rule? request, finding, rule
|
70
|
+
return false if finding.events.empty?
|
71
|
+
|
72
|
+
# We need to check for url exclusions here for the input rules as the url exclusions
|
73
|
+
# that have already been checked didn't include the INPUT exclusions. So we look for
|
74
|
+
# any INPUT exclusions that apply to the current url and the supplied rule.
|
75
|
+
path = request.path
|
76
|
+
rule_input_exclusions = assess_input_exclusions.select do |exclusion_matcher|
|
77
|
+
(exclusion_matcher.protection_rules.empty? || exclusion_matcher.protection_rules.include?(rule)) &&
|
78
|
+
path_match?(exclusion_matcher, path)
|
79
|
+
end
|
80
|
+
return false if rule_input_exclusions.empty?
|
81
|
+
|
82
|
+
event_sources = finding.events.flat_map(&:event_sources)
|
83
|
+
event_sources.each do |event_source|
|
84
|
+
return false unless rule_input_exclusions.any? do |exclusion|
|
85
|
+
input_match?(exclusion, event_source.type, event_source.name) # rubocop:disable Security/Module/Name
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# If we reach here, and we have event sources then all of them matched so we should exclude
|
90
|
+
# this finding. On the other hand, if there were no event sources we have nothing to exclude.
|
91
|
+
event_sources.any?
|
92
|
+
end
|
93
|
+
|
94
|
+
# If a protect URL exclusion rule applies to the current url, *and* is defined as "All Rules"
|
95
|
+
# then we can avoid using the rule for the request.
|
96
|
+
#
|
97
|
+
# @param request [Contrast::Agent::Request] a wrapper around the Rack::Request for the current request
|
98
|
+
# return [Boolean]
|
99
|
+
def protect_excluded_by_url? request
|
100
|
+
request_path = request.path
|
101
|
+
|
102
|
+
protect_url_exclusions_for_all_rules.any? do |exclusion_matcher|
|
103
|
+
path_match?(exclusion_matcher, request_path)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
110
|
+
def assess_url_exclusions_for_all_rules
|
111
|
+
@_assess_url_exclusions_for_all_rules ||= assess_url_exclusions.select do |exclusion_matcher|
|
112
|
+
exclusion_matcher.assess_rules.empty?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
117
|
+
def assess_url_exclusions
|
118
|
+
@_assess_url_exclusions ||= assess_exclusions.select do |exclusion_matcher|
|
119
|
+
exclusion_matcher.type == :URL
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
124
|
+
def assess_input_exclusions_for_all_rules
|
125
|
+
@_assess_input_exclusions_for_all_rules ||= assess_input_exclusions.select do |exclusion_matcher|
|
126
|
+
exclusion_matcher.assess_rules.empty?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
131
|
+
def assess_input_exclusions
|
132
|
+
@_assess_input_exclusions ||= assess_exclusions.select do |exclusion_matcher|
|
133
|
+
exclusion_matcher.type == :INPUT
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
138
|
+
def assess_exclusions
|
139
|
+
@_assess_exclusions ||= @exclusions.select(&:assess)
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
143
|
+
def protect_url_exclusions_for_all_rules
|
144
|
+
@_protect_url_exclusions_for_all_rules ||= protect_url_exclusions.select do |exclusion_matcher|
|
145
|
+
exclusion_matcher.protect_rules.empty?
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
150
|
+
def protect_url_exclusions
|
151
|
+
@_protect_url_exclusions ||= protect_exclusions.select do |exclusion_matcher|
|
152
|
+
exclusion_matcher.type == :URL
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# @return [Array<Contrast::Agent::ExclusionMatcher>]
|
157
|
+
def protect_exclusions
|
158
|
+
@_protect_exclusions ||= @exclusions.select(&:protect)
|
159
|
+
end
|
160
|
+
|
161
|
+
# @return [Boolean]
|
162
|
+
def path_match? exclusion_matcher, path
|
163
|
+
exclusion_matcher.wildcard_url || exclusion_matcher.urls.any? { |url| url.match?(path) }
|
164
|
+
end
|
165
|
+
|
166
|
+
# @param exclusion [Contrast::Agent::ExclusionMatcher]
|
167
|
+
# @param source_type [String]
|
168
|
+
# @param source_name [String]
|
169
|
+
# @return [Boolean]
|
170
|
+
def input_match? exclusion, source_type, source_name
|
171
|
+
case exclusion.input_type
|
172
|
+
when 'PARAMETER'
|
173
|
+
input_match_parameter?(exclusion, source_type, source_name)
|
174
|
+
when 'COOKIE'
|
175
|
+
input_match_cookie?(exclusion, source_type, source_name)
|
176
|
+
when 'HEADER'
|
177
|
+
input_match_header?(exclusion, source_type, source_name)
|
178
|
+
when 'BODY'
|
179
|
+
Contrast::Agent::Assess::Policy::SourceMethod::BODY_TYPE == source_type
|
180
|
+
when 'QUERYSTRING'
|
181
|
+
Contrast::Agent::Assess::Policy::SourceMethod::QUERYSTRING_TYPE == source_type
|
182
|
+
else
|
183
|
+
false
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def input_match_parameter? exclusion, source_type, source_name
|
188
|
+
return false unless [
|
189
|
+
Contrast::Agent::Assess::Policy::SourceMethod::PARAMETER_TYPE,
|
190
|
+
Contrast::Agent::Assess::Policy::SourceMethod::PARAMETER_KEY_TYPE
|
191
|
+
].include?(source_type)
|
192
|
+
|
193
|
+
exclusion.wildcard_input || (exclusion.input_name == source_name) || regexp_match?(exclusion.input_name,
|
194
|
+
source_name)
|
195
|
+
end
|
196
|
+
|
197
|
+
def input_match_cookie? exclusion, source_type, source_name
|
198
|
+
return false unless [
|
199
|
+
Contrast::Agent::Assess::Policy::SourceMethod::COOKIE_TYPE,
|
200
|
+
Contrast::Agent::Assess::Policy::SourceMethod::COOKIE_KEY_TYPE
|
201
|
+
].include?(source_type)
|
202
|
+
|
203
|
+
exclusion.wildcard_input || exclusion.input_name == source_name || regexp_match?(exclusion.input_name,
|
204
|
+
source_name)
|
205
|
+
end
|
206
|
+
|
207
|
+
def input_match_header? exclusion, source_type, source_name
|
208
|
+
return false unless [
|
209
|
+
Contrast::Agent::Assess::Policy::SourceMethod::HEADER_TYPE,
|
210
|
+
Contrast::Agent::Assess::Policy::SourceMethod::HEADER_KEY_TYPE
|
211
|
+
].include?(source_type)
|
212
|
+
|
213
|
+
exclusion.wildcard_input || exclusion.input_name.casecmp(source_name).zero? || regexp_match?(
|
214
|
+
exclusion.input_name, source_name)
|
215
|
+
end
|
216
|
+
|
217
|
+
def regexp_match? possible_pattern, source_name
|
218
|
+
Regexp.new("^#{ possible_pattern }$").match?(source_name)
|
219
|
+
rescue RegexpError
|
220
|
+
false
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -2,6 +2,10 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'contrast/components/logger'
|
5
|
+
require 'contrast/agent/reporting/settings/exclusion_base'
|
6
|
+
require 'contrast/agent/reporting/settings/code_exclusion'
|
7
|
+
require 'contrast/agent/reporting/settings/input_exclusion'
|
8
|
+
require 'contrast/agent/reporting/settings/url_exclusion'
|
5
9
|
|
6
10
|
module Contrast
|
7
11
|
module Agent
|
@@ -11,18 +15,32 @@ module Contrast
|
|
11
15
|
class ExclusionMatcher
|
12
16
|
include Contrast::Components::Logger::InstanceMethods
|
13
17
|
|
18
|
+
extend Forwardable
|
19
|
+
|
20
|
+
attr_reader :protect, :assess, :type, :urls, :wildcard_url, :wildcard_input
|
21
|
+
|
22
|
+
def_delegators :@exclusion, :protect_rules, :assess_rules, :input_type, :input_name
|
23
|
+
|
14
24
|
# Create a matcher around an exclusion sent from TeamServer.
|
15
25
|
#
|
16
|
-
# @param excl [Contrast::
|
26
|
+
# @param excl [Contrast::Agent::Reporting::Settings::ExclusionBase]
|
17
27
|
# @return [Contrast::Agent::ExclusionMatcher]
|
18
28
|
def initialize excl
|
19
29
|
@exclusion = excl
|
20
30
|
@protect = @exclusion.protect
|
21
31
|
@assess = @exclusion.assess
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
|
33
|
+
case excl
|
34
|
+
when Contrast::Agent::Reporting::Settings::CodeExclusion
|
35
|
+
handle_wildcard_code
|
36
|
+
@type = :CODE
|
37
|
+
when Contrast::Agent::Reporting::Settings::InputExclusion
|
38
|
+
handle_wildcard_input
|
39
|
+
@type = :INPUT
|
40
|
+
when Contrast::Agent::Reporting::Settings::UrlExclusion
|
41
|
+
handle_wildcard_url
|
42
|
+
@type = :URL
|
43
|
+
end
|
26
44
|
end
|
27
45
|
|
28
46
|
# According to the docs for exclusions, user input applies to all inputs if
|
@@ -91,7 +109,7 @@ module Contrast
|
|
91
109
|
end
|
92
110
|
|
93
111
|
def code?
|
94
|
-
@
|
112
|
+
@type == :CODE
|
95
113
|
end
|
96
114
|
|
97
115
|
def match_all?
|
@@ -99,12 +117,12 @@ module Contrast
|
|
99
117
|
end
|
100
118
|
|
101
119
|
# Determine if the given rule is excluded by this exclusion.
|
102
|
-
# In this case, the `
|
120
|
+
# In this case, the `protect_rules` being empty means apply to all rules,
|
103
121
|
# not no rules
|
104
122
|
#
|
105
123
|
# @param rule - the id of the rule which we're checking for exclusion
|
106
124
|
def protection_rule? rule
|
107
|
-
protect? && (@exclusion.
|
125
|
+
protect? && (@exclusion.protect_rules.empty? || @exclusion.protect_rules.include?(rule))
|
108
126
|
end
|
109
127
|
|
110
128
|
# Determine if the given rule is excluded by this exclusion.
|