contrast-agent 6.1.2 → 6.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -3
- data/.simplecov +1 -0
- data/Rakefile +0 -27
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +7 -5
- data/ext/cs__assess_kernel/cs__assess_kernel.c +14 -3
- data/ext/cs__assess_kernel/cs__assess_kernel.h +2 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +10 -3
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +2 -1
- data/ext/cs__assess_regexp/cs__assess_regexp.c +9 -7
- data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.c → cs__assess_string_interpolation/cs__assess_string_interpolation.c} +14 -3
- data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.h → cs__assess_string_interpolation/cs__assess_string_interpolation.h} +1 -1
- data/ext/{cs__assess_string_interpolation26 → cs__assess_string_interpolation}/extconf.rb +0 -0
- data/ext/cs__common/cs__common.c +5 -4
- data/ext/cs__contrast_patch/cs__contrast_patch.c +3 -10
- data/lib/contrast/agent/assess/events/source_event.rb +16 -12
- data/lib/contrast/agent/assess/policy/policy_node.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagation_method.rb +3 -41
- data/lib/contrast/agent/assess/policy/propagation_node.rb +8 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +2 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +2 -47
- data/lib/contrast/agent/assess/policy/source_node.rb +1 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_node.rb +8 -0
- data/lib/contrast/agent/assess/property/evented.rb +4 -18
- data/lib/contrast/agent/assess/tag.rb +19 -0
- data/lib/contrast/agent/at_exit_hook.rb +9 -8
- data/lib/contrast/agent/inventory/database_config.rb +6 -3
- data/lib/contrast/agent/inventory/dependency_analysis.rb +3 -2
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +13 -9
- data/lib/contrast/agent/middleware.rb +4 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +27 -2
- data/lib/contrast/agent/patching/policy/policy.rb +5 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +6 -0
- data/lib/contrast/agent/patching/policy/trigger_node.rb +3 -0
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +3 -4
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -0
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +2 -2
- data/lib/contrast/agent/protect/rule/base.rb +1 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +2 -0
- data/lib/contrast/agent/protect/rule/xss.rb +4 -0
- data/lib/contrast/agent/reporting/reporter.rb +33 -17
- data/lib/contrast/agent/reporting/reporter_heartbeat.rb +21 -15
- data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +3 -18
- data/lib/contrast/agent/reporting/reporting_events/application_update.rb +5 -24
- data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +83 -16
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +9 -3
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +12 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +29 -32
- data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +18 -20
- data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +11 -24
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +13 -6
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -4
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +10 -4
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +9 -0
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +11 -4
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -8
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +2 -6
- data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -32
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -4
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +1 -11
- data/lib/contrast/agent/reporting/reporting_utilities/response.rb +60 -2
- data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +32 -10
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +58 -26
- data/lib/contrast/agent/reporting/settings/application_settings.rb +8 -23
- data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +27 -33
- data/lib/contrast/agent/reporting/settings/bot_blocker.rb +68 -0
- data/lib/contrast/agent/reporting/settings/code_exclusion.rb +27 -0
- data/lib/contrast/agent/reporting/settings/exclusion_base.rb +33 -0
- data/lib/contrast/agent/reporting/settings/exclusions.rb +39 -57
- data/lib/contrast/agent/reporting/settings/helpers.rb +56 -0
- data/lib/contrast/agent/reporting/settings/input_exclusion.rb +37 -0
- data/lib/contrast/agent/reporting/settings/ip_filter.rb +35 -0
- data/lib/contrast/agent/reporting/settings/keyword.rb +74 -0
- data/lib/contrast/agent/reporting/settings/log_enhancer.rb +65 -0
- data/lib/contrast/agent/reporting/settings/protect.rb +4 -2
- data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +62 -115
- data/lib/contrast/agent/reporting/settings/reaction.rb +11 -2
- data/lib/contrast/agent/reporting/settings/rule_definition.rb +63 -0
- data/lib/contrast/agent/reporting/settings/sampling.rb +10 -0
- data/lib/contrast/agent/reporting/settings/sanitizer.rb +38 -0
- data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +9 -1
- data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +7 -0
- data/lib/contrast/agent/reporting/settings/server_features.rb +8 -0
- data/lib/contrast/agent/reporting/settings/syslog.rb +176 -0
- data/lib/contrast/agent/reporting/settings/url_exclusion.rb +42 -0
- data/lib/contrast/agent/reporting/settings/validator.rb +17 -0
- data/lib/contrast/agent/request.rb +5 -7
- data/lib/contrast/agent/request_context.rb +8 -13
- data/lib/contrast/agent/request_context_extend.rb +8 -9
- data/lib/contrast/agent/request_handler.rb +10 -35
- data/lib/contrast/agent/rule_set.rb +4 -0
- data/lib/contrast/agent/service_heartbeat.rb +1 -1
- data/lib/contrast/agent/static_analysis.rb +6 -15
- data/lib/contrast/agent/telemetry/base.rb +35 -35
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +2 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +2 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +5 -2
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +3 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +3 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +0 -1
- data/lib/contrast/agent/thread_watcher.rb +2 -6
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +1 -3
- data/lib/contrast/api/communication/socket.rb +1 -0
- data/lib/contrast/api/decorators/message.rb +0 -6
- data/lib/contrast/api/decorators.rb +0 -3
- data/lib/contrast/api/dtm.pb.rb +1 -1
- data/lib/contrast/api/settings.pb.rb +1 -1
- data/lib/contrast/components/assess.rb +0 -6
- data/lib/contrast/components/config.rb +18 -2
- data/lib/contrast/config/base_configuration.rb +0 -13
- data/lib/contrast/config/root_configuration.rb +1 -0
- data/lib/contrast/config/ruby_configuration.rb +2 -9
- data/lib/contrast/configuration.rb +0 -2
- data/lib/contrast/extension/assess/eval_trigger.rb +0 -4
- data/lib/contrast/extension/assess/hash.rb +3 -2
- data/lib/contrast/extension/assess/kernel.rb +22 -0
- data/lib/contrast/extension/assess/marshal.rb +16 -0
- data/lib/contrast/extension/assess/string.rb +21 -20
- data/lib/contrast/framework/base_support.rb +13 -4
- data/lib/contrast/framework/grape/support.rb +6 -6
- data/lib/contrast/framework/manager.rb +7 -23
- data/lib/contrast/framework/manager_extend.rb +1 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +11 -15
- data/lib/contrast/framework/rails/support.rb +9 -2
- data/lib/contrast/framework/sinatra/support.rb +3 -2
- data/lib/contrast/logger/aliased_logging.rb +33 -26
- data/lib/contrast/utils/assess/source_method_utils.rb +0 -9
- data/lib/contrast/utils/lru_cache.rb +3 -0
- data/lib/contrast/utils/middleware_utils.rb +2 -0
- data/lib/contrast/utils/patching/policy/patch_utils.rb +5 -22
- data/lib/contrast/utils/response_utils.rb +14 -1
- data/lib/contrast/utils/telemetry.rb +9 -0
- data/lib/contrast/utils/telemetry_client.rb +7 -7
- data/lib/contrast/utils/telemetry_hash.rb +36 -12
- data/lib/contrast/utils/telemetry_identifier.rb +8 -0
- data/lib/contrast/utils/thread_tracker.rb +26 -9
- data/lib/contrast/utils/timer.rb +6 -1
- data/lib/contrast.rb +35 -3
- data/lib/protobuf/code_generator.rb +129 -0
- data/lib/protobuf/decoder.rb +28 -0
- data/lib/protobuf/deprecation.rb +117 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +79 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +360 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/encoder.rb +11 -0
- data/lib/protobuf/enum.rb +365 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field/base_field.rb +380 -0
- data/lib/protobuf/field/base_field_object_definitions.rb +504 -0
- data/lib/protobuf/field/bool_field.rb +64 -0
- data/lib/protobuf/field/bytes_field.rb +67 -0
- data/lib/protobuf/field/double_field.rb +25 -0
- data/lib/protobuf/field/enum_field.rb +56 -0
- data/lib/protobuf/field/field_array.rb +102 -0
- data/lib/protobuf/field/field_hash.rb +122 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +28 -0
- data/lib/protobuf/field/float_field.rb +43 -0
- data/lib/protobuf/field/int32_field.rb +21 -0
- data/lib/protobuf/field/int64_field.rb +34 -0
- data/lib/protobuf/field/integer_field.rb +23 -0
- data/lib/protobuf/field/message_field.rb +51 -0
- data/lib/protobuf/field/sfixed32_field.rb +27 -0
- data/lib/protobuf/field/sfixed64_field.rb +28 -0
- data/lib/protobuf/field/signed_integer_field.rb +29 -0
- data/lib/protobuf/field/sint32_field.rb +21 -0
- data/lib/protobuf/field/sint64_field.rb +21 -0
- data/lib/protobuf/field/string_field.rb +51 -0
- data/lib/protobuf/field/uint32_field.rb +21 -0
- data/lib/protobuf/field/uint64_field.rb +21 -0
- data/lib/protobuf/field/varint_field.rb +77 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/generators/base.rb +85 -0
- data/lib/protobuf/generators/enum_generator.rb +39 -0
- data/lib/protobuf/generators/extension_generator.rb +27 -0
- data/lib/protobuf/generators/field_generator.rb +193 -0
- data/lib/protobuf/generators/file_generator.rb +262 -0
- data/lib/protobuf/generators/group_generator.rb +122 -0
- data/lib/protobuf/generators/message_generator.rb +104 -0
- data/lib/protobuf/generators/option_generator.rb +17 -0
- data/lib/protobuf/generators/printable.rb +160 -0
- data/lib/protobuf/generators/service_generator.rb +50 -0
- data/lib/protobuf/lifecycle.rb +33 -0
- data/lib/protobuf/logging.rb +39 -0
- data/lib/protobuf/message/fields.rb +233 -0
- data/lib/protobuf/message/serialization.rb +85 -0
- data/lib/protobuf/message.rb +241 -0
- data/lib/protobuf/optionable.rb +72 -0
- data/lib/protobuf/tasks/compile.rake +80 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/varint.rb +20 -0
- data/lib/protobuf/varint_pure.rb +31 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf.rb +91 -0
- data/proto/dynamic_discovery.proto +46 -0
- data/proto/google/protobuf/compiler/plugin.proto +183 -0
- data/proto/google/protobuf/descriptor.proto +911 -0
- data/proto/rpc.proto +71 -0
- data/resources/assess/policy.json +2 -11
- data/ruby-agent.gemspec +2 -2
- metadata +105 -30
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +0 -30
- data/lib/contrast/api/decorators/application_update.rb +0 -52
- data/lib/contrast/api/decorators/library.rb +0 -56
- data/lib/contrast/api/decorators/library_usage_update.rb +0 -31
- data/lib/contrast/framework/platform_version.rb +0 -22
@@ -7,7 +7,6 @@ require 'contrast/utils/telemetry_client'
|
|
7
7
|
require 'contrast/agent/worker_thread'
|
8
8
|
require 'contrast/utils/telemetry'
|
9
9
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions'
|
10
|
-
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report'
|
11
10
|
|
12
11
|
module Contrast
|
13
12
|
module Agent
|
@@ -15,7 +14,6 @@ module Contrast
|
|
15
14
|
# This class will initialize and hold everything needed for the telemetry
|
16
15
|
class Base < WorkerThread
|
17
16
|
include Contrast::Components::Logger::InstanceMethods
|
18
|
-
include Contrast::Agent::Telemetry::TelemetryExceptionReport
|
19
17
|
|
20
18
|
# this is where we will send the data from the agents
|
21
19
|
URL = 'https://telemetry.ruby.contrastsecurity.com/'
|
@@ -66,10 +64,6 @@ module Contrast
|
|
66
64
|
@_connection ||= client.initialize_connection(URL)
|
67
65
|
end
|
68
66
|
|
69
|
-
def error_messages
|
70
|
-
@_error_messages ||= []
|
71
|
-
end
|
72
|
-
|
73
67
|
def attempt_to_start?
|
74
68
|
unless cs__class.enabled?
|
75
69
|
logger.warn('Telemetry service is disabled!')
|
@@ -83,34 +77,8 @@ module Contrast
|
|
83
77
|
def start_thread!
|
84
78
|
return if running?
|
85
79
|
|
86
|
-
|
87
|
-
|
88
|
-
@_thread = Contrast::Agent::Thread.new do
|
89
|
-
logger.debug('Starting background telemetry thread.')
|
90
|
-
loop do
|
91
|
-
next unless client && connection
|
92
|
-
|
93
|
-
# Start pushing exceptions to queue for reporting.
|
94
|
-
push_exceptions
|
95
|
-
until queue.empty?
|
96
|
-
event = queue.pop
|
97
|
-
begin
|
98
|
-
logger.debug('This is the current processed event', event)
|
99
|
-
sleep_time = request_with_response(event)
|
100
|
-
if sleep_time
|
101
|
-
sleep(sleep_time)
|
102
|
-
logger.debug('Retrying to process event', event)
|
103
|
-
retry_sleep_time = request_with_response(event)
|
104
|
-
sleep(retry_sleep_time) unless retry_sleep_time.nil?
|
105
|
-
end
|
106
|
-
rescue StandardError => e
|
107
|
-
logger.error('Could not send message to service from telemetry queue.', e)
|
108
|
-
stop!
|
109
|
-
end
|
110
|
-
end
|
111
|
-
sleep(SUGGESTED_TIMEOUT)
|
112
|
-
end
|
113
|
-
end
|
80
|
+
logger.debug('Starting background telemetry thread.')
|
81
|
+
@_thread = create_thread
|
114
82
|
end
|
115
83
|
|
116
84
|
def send_event event
|
@@ -126,7 +94,6 @@ module Contrast
|
|
126
94
|
end
|
127
95
|
|
128
96
|
def delete_queue!
|
129
|
-
@_queue&.clear
|
130
97
|
@_queue&.close
|
131
98
|
@_queue = nil
|
132
99
|
end
|
@@ -149,6 +116,39 @@ module Contrast
|
|
149
116
|
def queue
|
150
117
|
@_queue ||= Queue.new
|
151
118
|
end
|
119
|
+
|
120
|
+
# It is recommended that implementations send a single payload of general metrics every 3 hours, starting from
|
121
|
+
# implementation startup. This returns a thread configured to do so.
|
122
|
+
#
|
123
|
+
# @return [Contrast::Agent::Thread]
|
124
|
+
def create_thread
|
125
|
+
Contrast::Agent::Thread.new do
|
126
|
+
loop do
|
127
|
+
next unless client && connection
|
128
|
+
|
129
|
+
# Start pushing exceptions to queue for reporting.
|
130
|
+
Contrast::TELEMETRY_EXCEPTIONS.each_value { |value| queue << value }
|
131
|
+
Contrast::TELEMETRY_EXCEPTIONS.clear
|
132
|
+
until queue.empty?
|
133
|
+
event = queue.pop
|
134
|
+
begin
|
135
|
+
logger.debug('This is the current processed event', event)
|
136
|
+
sleep_time = request_with_response(event)
|
137
|
+
if sleep_time
|
138
|
+
sleep(sleep_time)
|
139
|
+
logger.debug('Retrying to process event', event)
|
140
|
+
retry_sleep_time = request_with_response(event)
|
141
|
+
sleep(retry_sleep_time) unless retry_sleep_time.nil?
|
142
|
+
end
|
143
|
+
rescue StandardError => e
|
144
|
+
logger.error('Could not send message to service from telemetry queue.', e)
|
145
|
+
stop!
|
146
|
+
end
|
147
|
+
end
|
148
|
+
sleep(SUGGESTED_TIMEOUT)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
152
|
end
|
153
153
|
end
|
154
154
|
end
|
@@ -28,6 +28,7 @@ module Contrast
|
|
28
28
|
#
|
29
29
|
# @param validation_pair [Hash] Validation hash to use
|
30
30
|
# @param key[String] The key to check in VALIDATIONS
|
31
|
+
# @raise [ArgumentError]
|
31
32
|
def validate_field validation_pair, key
|
32
33
|
value_to_validate = send(key.to_sym)
|
33
34
|
validate_class(value_to_validate, validation_pair[:class], key) if validation_pair.key?(:class)
|
@@ -48,6 +49,7 @@ module Contrast
|
|
48
49
|
# @param message [Object] The message we want to check the class of
|
49
50
|
# @param klass [Class] The klass we want to check the message with
|
50
51
|
# @param field [Object] The field with the error
|
52
|
+
# @raise [ArgumentError]
|
51
53
|
def validate_class message, klass, field
|
52
54
|
message = message[0] if message.cs__is_a?(Array)
|
53
55
|
raise(ArgumentError, "The provided value for #{ field } is of wrong class") unless message.cs__is_a?(klass)
|
@@ -18,6 +18,7 @@ module Contrast
|
|
18
18
|
# to be created
|
19
19
|
#
|
20
20
|
# @param message [Contrast::Agent::Telemetry::TelemetryException::Message]
|
21
|
+
# @raise[ArgumentError]
|
21
22
|
def initialize message
|
22
23
|
super()
|
23
24
|
validate_class(message, Contrast::Agent::Telemetry::TelemetryException::Message, 'exception_message')
|
@@ -25,6 +26,7 @@ module Contrast
|
|
25
26
|
end
|
26
27
|
|
27
28
|
# @param message [Contrast::Agent::Telemetry::TelemetryException::Message]
|
29
|
+
# @raise[ArgumentError]
|
28
30
|
def push message
|
29
31
|
validate_class(message, Contrast::Agent::Telemetry::TelemetryException::Message, 'exception_message')
|
30
32
|
@exceptions << message
|
@@ -50,6 +50,7 @@ module Contrast
|
|
50
50
|
# @return [String | nil] A string message to provide additional context to the errors.
|
51
51
|
attr_reader :message
|
52
52
|
|
53
|
+
# @raise[ArgumentError]
|
53
54
|
def initialize instance, tags, exceptions
|
54
55
|
super()
|
55
56
|
@tags = tags
|
@@ -63,17 +64,19 @@ module Contrast
|
|
63
64
|
# Optional parameters will be set separately from the required
|
64
65
|
#
|
65
66
|
# @param logger[String]
|
67
|
+
# @raise[ArgumentError]
|
66
68
|
def logger= logger
|
67
|
-
validate_field(VALIDATIONS[:logger], 'logger')
|
68
69
|
@logger = logger
|
70
|
+
validate_field(VALIDATIONS[:logger], 'logger')
|
69
71
|
end
|
70
72
|
|
71
73
|
# Optional parameters will be set separately from the required
|
72
74
|
#
|
73
75
|
# @param message[String]
|
76
|
+
# @raise[ArgumentError]
|
74
77
|
def message= message
|
75
|
-
validate_field(VALIDATIONS[:message], 'message')
|
76
78
|
@message = message
|
79
|
+
validate_field(VALIDATIONS[:message], 'message')
|
77
80
|
end
|
78
81
|
|
79
82
|
# Optional parameters will be set separately from the required
|
data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb
CHANGED
@@ -43,16 +43,19 @@ module Contrast
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# @param stack_frame [Contrast::Agent::Telemetry::TelemetryException::StackFrame]
|
46
|
+
# @raise[ArgumentError]
|
46
47
|
def push stack_frame
|
47
48
|
validate_class(stack_frame, Contrast::Agent::Telemetry::TelemetryException::StackFrame, 'stack_frame')
|
48
49
|
@stack_frames << stack_frame
|
49
50
|
end
|
50
51
|
|
52
|
+
# @raise[ArgumentError]
|
51
53
|
def module_name= module_name
|
52
54
|
@module_name = module_name
|
53
55
|
validate_field(VALIDATIONS[:module_name], 'module_name')
|
54
56
|
end
|
55
57
|
|
58
|
+
# @raise[ArgumentError]
|
56
59
|
def value= value
|
57
60
|
@value = value
|
58
61
|
validate_field(VALIDATIONS[:value], 'value')
|
@@ -28,6 +28,7 @@ module Contrast
|
|
28
28
|
# @return [String]
|
29
29
|
attr_reader :module_name
|
30
30
|
|
31
|
+
# @raise [ArgumentError]
|
31
32
|
def initialize function, type
|
32
33
|
super()
|
33
34
|
@function = function
|
@@ -36,11 +37,13 @@ module Contrast
|
|
36
37
|
validate(VALIDATIONS)
|
37
38
|
end
|
38
39
|
|
40
|
+
# @raise [ArgumentError]
|
39
41
|
def module_name= module_name
|
40
42
|
@module_name = module_name
|
41
43
|
validate_field(VALIDATIONS[:module_name], 'module_name')
|
42
44
|
end
|
43
45
|
|
46
|
+
# @raise [ArgumentError]
|
44
47
|
def to_controlled_hash
|
45
48
|
super
|
46
49
|
{ function: function, type: type, module: module_name, inContrast: in_contrast }.compact
|
@@ -17,4 +17,3 @@ require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_fr
|
|
17
17
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception'
|
18
18
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_message'
|
19
19
|
require 'contrast/agent/telemetry/events/exceptions/telemetry_exception_event'
|
20
|
-
require 'contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report'
|
@@ -32,10 +32,8 @@ module Contrast
|
|
32
32
|
@heartbeat = Contrast::Agent::ServiceHeartbeat.new
|
33
33
|
@messaging_queue = Contrast::Api::Communication::MessagingQueue.new
|
34
34
|
end
|
35
|
-
|
36
|
-
|
37
|
-
@reporter_heartbeat = Contrast::Agent::ReporterHeartbeat.new
|
38
|
-
end
|
35
|
+
@reporter = Contrast::Agent::Reporter.new
|
36
|
+
@reporter_heartbeat = Contrast::Agent::ReporterHeartbeat.new
|
39
37
|
@telemetry = Contrast::Agent::Telemetry::Base.new if Contrast::Agent::Telemetry::Base.enabled?
|
40
38
|
end
|
41
39
|
|
@@ -51,8 +49,6 @@ module Contrast
|
|
51
49
|
telemetry_status = init_thread(telemetry_queue)
|
52
50
|
@pids[Process.pid] = @pids[Process.pid] && telemetry_status
|
53
51
|
end
|
54
|
-
return @pids unless Contrast::Agent::Reporter.enabled?
|
55
|
-
|
56
52
|
reporter_status = init_thread(reporter)
|
57
53
|
reporter_heartbeat_status = init_thread(reporter_heartbeat)
|
58
54
|
@pids[Process.pid] = @pids[Process.pid] && reporter_status && reporter_heartbeat_status
|
data/lib/contrast/agent.rb
CHANGED
@@ -34,6 +34,7 @@ module Contrast
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# Override this method to return a socket. Should be interface compatible with TCPSocket, UNIXSocket, etc.
|
37
|
+
# @raise[NoMethodError] abstract method, needs to be implemented
|
37
38
|
def new_socket
|
38
39
|
raise(NoMethodError, 'This is abstract, override it.')
|
39
40
|
end
|
@@ -19,14 +19,10 @@ module Contrast
|
|
19
19
|
|
20
20
|
def append_event event
|
21
21
|
case event
|
22
|
-
when Contrast::Api::Dtm::ServerActivity
|
23
|
-
self.server_activity = event
|
24
22
|
when Contrast::Api::Dtm::AgentStartup
|
25
23
|
self.agent_startup = event
|
26
24
|
when Contrast::Api::Dtm::ApplicationCreate
|
27
25
|
self.application_create = event
|
28
|
-
when Contrast::Api::Dtm::ApplicationUpdate
|
29
|
-
self.application_update = event
|
30
26
|
when Contrast::Api::Dtm::Activity
|
31
27
|
self.activity = event
|
32
28
|
when Contrast::Api::Dtm::HttpRequest
|
@@ -35,8 +31,6 @@ module Contrast
|
|
35
31
|
self.postfilter = event
|
36
32
|
when Contrast::Api::Dtm::Poll
|
37
33
|
self.poll = event
|
38
|
-
when Contrast::Api::Dtm::ObservedRoute
|
39
|
-
self.observed_route = event
|
40
34
|
else
|
41
35
|
logger.error('Unknown event type received. Unsure how to send.', event_type: event.cs__class.cs__name)
|
42
36
|
return
|
@@ -12,13 +12,10 @@ end
|
|
12
12
|
require 'contrast/api/decorators/message'
|
13
13
|
require 'contrast/api/decorators/agent_startup'
|
14
14
|
require 'contrast/api/decorators/application_startup'
|
15
|
-
require 'contrast/api/decorators/application_update'
|
16
15
|
require 'contrast/api/decorators/architecture_component'
|
17
16
|
require 'contrast/api/decorators/input_analysis'
|
18
17
|
require 'contrast/api/decorators/application_settings'
|
19
18
|
require 'contrast/api/decorators/server_features'
|
20
|
-
require 'contrast/api/decorators/library'
|
21
|
-
require 'contrast/api/decorators/library_usage_update'
|
22
19
|
require 'contrast/api/decorators/route_coverage'
|
23
20
|
require 'contrast/api/decorators/trace_event_object'
|
24
21
|
require 'contrast/api/decorators/trace_event_signature'
|
data/lib/contrast/api/dtm.pb.rb
CHANGED
@@ -76,12 +76,6 @@ module Contrast
|
|
76
76
|
@_scan_response
|
77
77
|
end
|
78
78
|
|
79
|
-
def track_frozen_sources?
|
80
|
-
@_track_frozen_sources = !false?(::Contrast::CONFIG.root.agent.ruby.track_frozen_sources) if
|
81
|
-
@_track_frozen_sources.nil?
|
82
|
-
@_track_frozen_sources
|
83
|
-
end
|
84
|
-
|
85
79
|
def require_scan?
|
86
80
|
@_require_scan = !false?(::Contrast::CONFIG.root.agent.ruby.require_scan) if @_require_scan.nil?
|
87
81
|
@_require_scan
|
@@ -27,7 +27,7 @@ module Contrast
|
|
27
27
|
CONTRAST_LOG = 'contrast_agent.log'
|
28
28
|
CONTRAST_NAME = 'Contrast Agent'
|
29
29
|
|
30
|
-
class Interface # :nodoc:
|
30
|
+
class Interface # :nodoc: # rubocop:disable Metrics/ClassLength
|
31
31
|
SESSION_VARIABLES = 'Invalid configuration. '\
|
32
32
|
"Setting both application.session_id and application.session_metadata is not allowed.\n"
|
33
33
|
API_URL = "Invalid configuration. Missing a required connection value 'url' is not set."
|
@@ -57,6 +57,8 @@ module Contrast
|
|
57
57
|
@config = Contrast::Configuration.new
|
58
58
|
env_overrides
|
59
59
|
validate
|
60
|
+
rescue ArgumentError => e
|
61
|
+
proto_logger.error('Configuration failed with error: ', e)
|
60
62
|
end
|
61
63
|
alias_method :rebuild, :build
|
62
64
|
|
@@ -136,7 +138,7 @@ module Contrast
|
|
136
138
|
next unless env_key.to_s.start_with?(CONTRAST_ENV_MARKER)
|
137
139
|
|
138
140
|
config_item = Contrast::Utils::EnvConfigurationItem.new(env_key, env_value)
|
139
|
-
|
141
|
+
assign_value_to_path_array(root, config_item.dot_path_array, config_item.value)
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
@@ -193,6 +195,20 @@ module Contrast
|
|
193
195
|
def logger_path
|
194
196
|
root.agent.logger.path
|
195
197
|
end
|
198
|
+
|
199
|
+
# Assign the value from an ENV variable to the Contrast::Config::RootConfiguration object, when
|
200
|
+
# appropriate.
|
201
|
+
#
|
202
|
+
# @return nil
|
203
|
+
def assign_value_to_path_array current_level, dot_path_array, value
|
204
|
+
dot_path_array[0...-1].each do |segment|
|
205
|
+
segment = segment.tr('-', '_')
|
206
|
+
current_level = current_level.send(segment) if current_level.cs__respond_to?(segment)
|
207
|
+
end
|
208
|
+
return unless current_level.nil? == false && current_level.cs__respond_to?(dot_path_array[-1])
|
209
|
+
|
210
|
+
current_level.send("#{ dot_path_array[-1] }=", value)
|
211
|
+
end
|
196
212
|
end
|
197
213
|
end
|
198
214
|
end
|
@@ -20,19 +20,6 @@ module Contrast
|
|
20
20
|
end
|
21
21
|
hsh
|
22
22
|
end
|
23
|
-
|
24
|
-
def assign_value_to_path_array dot_path_array, value
|
25
|
-
current_level = self
|
26
|
-
dot_path_array[0...-1].each do |segment|
|
27
|
-
segment = segment.tr('-', '_')
|
28
|
-
current_level = current_level.send(segment) if current_level.cs__respond_to?(segment)
|
29
|
-
end
|
30
|
-
last_entry = dot_path_array[-1]
|
31
|
-
if current_level.nil? == false && current_level.cs__respond_to?(last_entry)
|
32
|
-
current_level.send("#{ last_entry }=", value)
|
33
|
-
end
|
34
|
-
nil
|
35
|
-
end
|
36
23
|
end
|
37
24
|
end
|
38
25
|
end
|
@@ -21,7 +21,7 @@ module Contrast
|
|
21
21
|
DEFAULT_UNINSTRUMENTED_NAMESPACES = %w[FactoryGirl FactoryBot].cs__freeze
|
22
22
|
|
23
23
|
attr_writer :disabled_agent_rake_tasks, :exceptions, :interpolate, :propagate_yield, :require_scan,
|
24
|
-
:
|
24
|
+
:non_request_tracking, :uninstrument_namespace
|
25
25
|
|
26
26
|
def initialize hsh = {}
|
27
27
|
return unless hsh
|
@@ -31,7 +31,6 @@ module Contrast
|
|
31
31
|
@interpolate = hsh[:interpolate]
|
32
32
|
@propagate_yield = hsh[:propagate_yield]
|
33
33
|
@require_scan = hsh[:require_scan]
|
34
|
-
@track_frozen_sources = hsh[:track_frozen_sources]
|
35
34
|
@non_request_tracking = hsh[:non_request_tracking]
|
36
35
|
@uninstrument_namespace = hsh[:uninstrument_namespace]
|
37
36
|
end
|
@@ -67,16 +66,10 @@ module Contrast
|
|
67
66
|
@require_scan.nil? ? Contrast::Utils::ObjectShare::TRUE : @require_scan
|
68
67
|
end
|
69
68
|
|
70
|
-
# controls whether or not we track frozen Strings by replacing them
|
71
|
-
# @return [Boolean, Contrast::Utils::ObjectShare::TRUE]
|
72
|
-
def track_frozen_sources
|
73
|
-
@track_frozen_sources.nil? ? Contrast::Utils::ObjectShare::TRUE : @track_frozen_sources
|
74
|
-
end
|
75
|
-
|
76
69
|
# controls tracking outside of request
|
77
70
|
# @return [Boolean, Contrast::Utils::ObjectShare::FALSE]
|
78
71
|
def non_request_tracking
|
79
|
-
@non_request_tracking.nil? ?
|
72
|
+
@non_request_tracking.nil? ? Contrast::Utils::ObjectShare::FALSE : @non_request_tracking
|
80
73
|
end
|
81
74
|
|
82
75
|
# @return [Array, DEFAULT_UNINSTRUMENTED_NAMESPACES]
|
@@ -18,8 +18,6 @@ module Contrast
|
|
18
18
|
include Contrast::Components::Scope::InstanceMethods
|
19
19
|
extend Contrast::Components::Scope::InstanceMethods
|
20
20
|
|
21
|
-
def_delegator :root, :assign_value_to_path_array
|
22
|
-
|
23
21
|
attr_reader :default_name, :root
|
24
22
|
|
25
23
|
DEFAULT_YAML_PATH = 'contrast_security.yaml'
|
@@ -25,10 +25,6 @@ module Contrast
|
|
25
25
|
def apply_trigger obj, source, ret, clazz, method
|
26
26
|
return unless ::Contrast::ASSESS.non_request_tracking? || Contrast::Agent::REQUEST_TRACKER.current
|
27
27
|
|
28
|
-
# Since we know this is the source of the trigger, we can do some
|
29
|
-
# optimization here and return when it is not tracked
|
30
|
-
return unless Contrast::Utils::Assess::TrackingUtil.tracked?(source)
|
31
|
-
|
32
28
|
# source might not be all the args passed in, but it is the one we care
|
33
29
|
# about. we could pass in all the args in the last param here if it
|
34
30
|
# becomes an issue in rendering on TS
|
@@ -15,11 +15,12 @@ module Contrast
|
|
15
15
|
class << self
|
16
16
|
def cs__duplicate_and_freeze object
|
17
17
|
return object unless object.is_a?(String) && !object.cs__frozen?
|
18
|
-
return object unless Contrast::Agent::Assess::Tracker.tracked?(object)
|
19
18
|
|
20
19
|
# Copy the object, then freeze it, so that it looks the same
|
21
20
|
# externally, but will have our finalizer on it.
|
22
|
-
object.dup
|
21
|
+
copy = object.dup
|
22
|
+
Contrast::Agent::Assess::Tracker.pre_freeze(copy)
|
23
|
+
copy&.cs__freeze
|
23
24
|
rescue StandardError
|
24
25
|
# we'll rescue this error, but we can't log it here as that will
|
25
26
|
# result in a seg fault
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require 'contrast/extension/assess/exec_trigger'
|
5
5
|
require 'contrast/components/logger'
|
6
6
|
require 'contrast/agent/assess/events/event_data'
|
7
|
+
require 'contrast/agent/patching/policy/patch'
|
7
8
|
|
8
9
|
module Contrast
|
9
10
|
module Extension
|
@@ -97,6 +98,27 @@ module Contrast
|
|
97
98
|
end
|
98
99
|
end
|
99
100
|
end
|
101
|
+
|
102
|
+
# Used for Kernel exec aliasing since we have no other way of accessing the
|
103
|
+
# Kernel#exec under C if we alias it there.
|
104
|
+
module ContrastKernel
|
105
|
+
# Method to replace the call to Kernel#exec when applying alias patch.
|
106
|
+
# It will invoke Contrast::Extension::Assess::KernelPropagator before
|
107
|
+
# calling the original method.
|
108
|
+
#
|
109
|
+
# @param source [String, Proc] Potentially untrusted shell command to execute.
|
110
|
+
# @return nil - This method will invoke the Kernel#exec which will
|
111
|
+
def cs__kernel_exec source
|
112
|
+
# Check if in contrast scope and we have source.
|
113
|
+
unless Contrast::Agent::Patching::Policy::Patch.in_contrast_scope? || source.nil?
|
114
|
+
Contrast::Agent::Patching::Policy::Patch.with_contrast_scope do
|
115
|
+
Contrast::Extension::Assess::KernelPropagator.apply_trigger(source)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
# Call this in the end else any code bellow this call won't be executed.
|
119
|
+
Kernel.exec(source)
|
120
|
+
end
|
121
|
+
end
|
100
122
|
end
|
101
123
|
end
|
102
124
|
end
|
@@ -58,6 +58,22 @@ module Contrast
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
61
|
+
|
62
|
+
# Used for aliasing
|
63
|
+
module ContrastMarshal
|
64
|
+
def cs__marshal_load source
|
65
|
+
# Do the protect
|
66
|
+
Contrast::Extension::Assess::MarshalPropagator.cs__load_protect(source) if source
|
67
|
+
# call the original
|
68
|
+
result = Marshal.load(source) # rubocop:disable Security/MarshalLoad
|
69
|
+
# Do the assess
|
70
|
+
tracked = Contrast::Agent::Assess::Tracker::PROPERTIES_HASH.tracked?(source) if source
|
71
|
+
skip = Contrast::Agent::Patching::Policy::Patch.skip_assess_analysis? if tracked
|
72
|
+
Contrast::Extension::Assess::MarshalPropagator.cs__load_assess(source, result) if skip
|
73
|
+
# return original
|
74
|
+
result
|
75
|
+
end
|
76
|
+
end
|
61
77
|
end
|
62
78
|
end
|
63
79
|
end
|
@@ -31,31 +31,32 @@ module Contrast
|
|
31
31
|
INTERPOLATION_NODE = Contrast::Agent::Assess::Policy::PropagationNode.new(NODE_HASH)
|
32
32
|
|
33
33
|
class << self
|
34
|
+
# We call this method from C, and the Scope check is happening there. If we are in
|
35
|
+
# Contrast Scope the method won't be invoked.
|
36
|
+
#
|
37
|
+
# @param inputs [Array<String>] Inputs for interpolation.
|
38
|
+
# @param result [String] The result from the interpolation.
|
34
39
|
def track_interpolation inputs, result
|
35
40
|
return unless ::Contrast::AGENT.interpolation_enabled?
|
36
|
-
return if in_contrast_scope?
|
37
41
|
return unless inputs.any? { |input| Contrast::Agent::Assess::Tracker.tracked?(input) }
|
42
|
+
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(result))
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
offset += input.length
|
48
|
-
parent_event = Contrast::Agent::Assess::Tracker.properties(input)&.event
|
49
|
-
parent_events << parent_event if parent_event
|
50
|
-
end
|
51
|
-
event_data = Contrast::Agent::Assess::Events::EventData.new(INTERPOLATION_NODE,
|
52
|
-
result,
|
53
|
-
inputs,
|
54
|
-
result,
|
55
|
-
inputs)
|
56
|
-
properties.build_event(event_data)
|
57
|
-
properties.event.instance_variable_set(:@_parent_events, parent_events)
|
44
|
+
parent_events = []
|
45
|
+
offset = 0
|
46
|
+
inputs.each do |input|
|
47
|
+
properties.copy_from(input, result, offset)
|
48
|
+
add_dynamic_sources_info(input, result)
|
49
|
+
offset += input.length
|
50
|
+
parent_event = Contrast::Agent::Assess::Tracker.properties(input)&.event
|
51
|
+
parent_events << parent_event if parent_event
|
58
52
|
end
|
53
|
+
event_data = Contrast::Agent::Assess::Events::EventData.new(INTERPOLATION_NODE,
|
54
|
+
result,
|
55
|
+
inputs,
|
56
|
+
result,
|
57
|
+
inputs)
|
58
|
+
properties.build_event(event_data)
|
59
|
+
properties.event.instance_variable_set(:@_parent_events, parent_events)
|
59
60
|
rescue StandardError => e
|
60
61
|
logger.error('Unable to track interpolation', e)
|
61
62
|
end
|