contrast-agent 4.6.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +1 -1
  3. data/Rakefile +1 -2
  4. data/ext/build_funchook.rb +3 -3
  5. data/ext/extconf_common.rb +1 -5
  6. data/lib/contrast/agent/assess.rb +1 -1
  7. data/lib/contrast/agent/assess/contrast_object.rb +2 -2
  8. data/lib/contrast/agent/assess/events/event_factory.rb +2 -1
  9. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +6 -3
  10. data/lib/contrast/agent/assess/policy/patcher.rb +10 -17
  11. data/lib/contrast/agent/assess/policy/policy_node.rb +25 -33
  12. data/lib/contrast/agent/assess/policy/preshift.rb +3 -1
  13. data/lib/contrast/agent/assess/policy/propagation_method.rb +6 -15
  14. data/lib/contrast/agent/assess/policy/propagation_node.rb +19 -8
  15. data/lib/contrast/agent/assess/policy/propagator/center.rb +2 -1
  16. data/lib/contrast/agent/assess/policy/propagator/insert.rb +3 -1
  17. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +2 -1
  18. data/lib/contrast/agent/assess/policy/propagator/select.rb +2 -12
  19. data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -7
  20. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -7
  21. data/lib/contrast/agent/assess/policy/propagator/trim.rb +3 -15
  22. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +6 -3
  23. data/lib/contrast/agent/assess/policy/source_method.rb +6 -6
  24. data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +1 -3
  25. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +5 -1
  26. data/lib/contrast/agent/assess/policy/trigger_method.rb +6 -15
  27. data/lib/contrast/agent/assess/policy/trigger_node.rb +2 -1
  28. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +4 -3
  29. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -2
  30. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -8
  31. data/lib/contrast/agent/assess/property/evented.rb +8 -5
  32. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +11 -5
  33. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +4 -1
  34. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +3 -5
  35. data/lib/contrast/agent/class_reopener.rb +3 -1
  36. data/lib/contrast/agent/disable_reaction.rb +1 -3
  37. data/lib/contrast/agent/exclusion_matcher.rb +5 -11
  38. data/lib/contrast/agent/inventory/dependencies.rb +2 -0
  39. data/lib/contrast/agent/middleware.rb +3 -5
  40. data/lib/contrast/agent/module_data.rb +3 -3
  41. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +6 -5
  42. data/lib/contrast/agent/patching/policy/method_policy.rb +6 -2
  43. data/lib/contrast/agent/patching/policy/module_policy.rb +14 -7
  44. data/lib/contrast/agent/patching/policy/patch.rb +11 -16
  45. data/lib/contrast/agent/patching/policy/patch_status.rb +6 -7
  46. data/lib/contrast/agent/patching/policy/patcher.rb +15 -12
  47. data/lib/contrast/agent/patching/policy/policy_node.rb +14 -4
  48. data/lib/contrast/agent/patching/policy/trigger_node.rb +21 -8
  49. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +1 -1
  50. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +1 -1
  51. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
  52. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +2 -3
  53. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -1
  54. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +5 -9
  55. data/lib/contrast/agent/protect/policy/rule_applicator.rb +5 -5
  56. data/lib/contrast/agent/protect/rule/base.rb +13 -16
  57. data/lib/contrast/agent/protect/rule/base_service.rb +9 -5
  58. data/lib/contrast/agent/protect/rule/cmd_injection.rb +14 -18
  59. data/lib/contrast/agent/protect/rule/deserialization.rb +6 -13
  60. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +3 -14
  61. data/lib/contrast/agent/protect/rule/no_sqli.rb +6 -2
  62. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -3
  63. data/lib/contrast/agent/protect/rule/path_traversal.rb +5 -5
  64. data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
  65. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +1 -1
  66. data/lib/contrast/agent/protect/rule/xss.rb +1 -1
  67. data/lib/contrast/agent/protect/rule/xxe.rb +5 -12
  68. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +1 -2
  69. data/lib/contrast/agent/reaction_processor.rb +11 -10
  70. data/lib/contrast/agent/request.rb +23 -23
  71. data/lib/contrast/agent/request_context.rb +9 -14
  72. data/lib/contrast/agent/rewriter.rb +5 -3
  73. data/lib/contrast/agent/service_heartbeat.rb +2 -3
  74. data/lib/contrast/agent/tracepoint_hook.rb +1 -1
  75. data/lib/contrast/agent/version.rb +1 -1
  76. data/lib/contrast/api/communication/response_processor.rb +2 -4
  77. data/lib/contrast/api/communication/service_lifecycle.rb +4 -2
  78. data/lib/contrast/api/communication/socket_client.rb +8 -21
  79. data/lib/contrast/api/communication/speedracer.rb +3 -7
  80. data/lib/contrast/api/decorators/application_startup.rb +6 -2
  81. data/lib/contrast/api/decorators/library.rb +8 -6
  82. data/lib/contrast/api/decorators/message.rb +3 -3
  83. data/lib/contrast/api/decorators/trace_event.rb +3 -1
  84. data/lib/contrast/api/decorators/trace_event_object.rb +1 -3
  85. data/lib/contrast/api/decorators/trace_taint_range_tags.rb +1 -6
  86. data/lib/contrast/components/agent.rb +9 -4
  87. data/lib/contrast/components/app_context.rb +6 -6
  88. data/lib/contrast/components/config.rb +2 -1
  89. data/lib/contrast/components/contrast_service.rb +7 -8
  90. data/lib/contrast/components/interface.rb +3 -2
  91. data/lib/contrast/components/sampling.rb +8 -2
  92. data/lib/contrast/components/settings.rb +4 -2
  93. data/lib/contrast/config/assess_rules_configuration.rb +1 -3
  94. data/lib/contrast/config/base_configuration.rb +4 -5
  95. data/lib/contrast/config/exception_configuration.rb +1 -5
  96. data/lib/contrast/config/heap_dump_configuration.rb +12 -6
  97. data/lib/contrast/config/logger_configuration.rb +1 -5
  98. data/lib/contrast/configuration.rb +3 -14
  99. data/lib/contrast/extension/assess/array.rb +1 -6
  100. data/lib/contrast/extension/assess/erb.rb +1 -7
  101. data/lib/contrast/extension/assess/eval_trigger.rb +2 -6
  102. data/lib/contrast/extension/assess/exec_trigger.rb +3 -9
  103. data/lib/contrast/extension/assess/fiber.rb +2 -12
  104. data/lib/contrast/extension/assess/kernel.rb +2 -9
  105. data/lib/contrast/extension/assess/marshal.rb +2 -6
  106. data/lib/contrast/extension/assess/regexp.rb +1 -6
  107. data/lib/contrast/extension/assess/string.rb +3 -1
  108. data/lib/contrast/extension/kernel.rb +4 -2
  109. data/lib/contrast/framework/manager.rb +1 -2
  110. data/lib/contrast/framework/rack/patch/session_cookie.rb +5 -18
  111. data/lib/contrast/framework/rack/patch/support.rb +6 -4
  112. data/lib/contrast/framework/rails/patch/assess_configuration.rb +7 -2
  113. data/lib/contrast/framework/rails/patch/support.rb +4 -2
  114. data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +4 -1
  115. data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +2 -0
  116. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +2 -0
  117. data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +2 -0
  118. data/lib/contrast/framework/rails/support.rb +2 -2
  119. data/lib/contrast/framework/sinatra/support.rb +3 -1
  120. data/lib/contrast/funchook/funchook.rb +1 -5
  121. data/lib/contrast/logger/application.rb +12 -9
  122. data/lib/contrast/logger/format.rb +2 -5
  123. data/lib/contrast/logger/log.rb +4 -3
  124. data/lib/contrast/logger/request.rb +1 -2
  125. data/lib/contrast/security_exception.rb +1 -1
  126. data/lib/contrast/tasks/service.rb +5 -1
  127. data/lib/contrast/utils/assess/tracking_util.rb +1 -2
  128. data/lib/contrast/utils/class_util.rb +0 -8
  129. data/lib/contrast/utils/hash_digest.rb +2 -5
  130. data/lib/contrast/utils/io_util.rb +1 -1
  131. data/lib/contrast/utils/job_servers_running.rb +9 -4
  132. data/lib/contrast/utils/os.rb +2 -1
  133. data/lib/contrast/utils/ruby_ast_rewriter.rb +2 -1
  134. data/ruby-agent.gemspec +13 -14
  135. data/sonar-project.properties +9 -0
  136. metadata +37 -36
@@ -186,13 +186,7 @@ module Contrast
186
186
 
187
187
  properties = Contrast::Agent::Assess::Tracker.properties(ret)
188
188
  args = preshift.args
189
- properties.build_event(
190
- patcher,
191
- ret,
192
- preshift.object,
193
- ret,
194
- args,
195
- 2)
189
+ properties.build_event(patcher, ret, preshift.object, ret, args, 2)
196
190
  properties.event.instance_variable_set(:@_parent_events, parent_events)
197
191
  end
198
192
  end
@@ -12,7 +12,6 @@ module Contrast
12
12
  # right' state soon.
13
13
  module Trim
14
14
  class << self
15
-
16
15
  # @param policy_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
17
16
  # propagation event.
18
17
  # @param preshift [Contrast::Agent::Assess::PreShift] The capture of the state of the code just prior to
@@ -26,13 +25,7 @@ module Contrast
26
25
  properties.copy_from(preshift.object, ret)
27
26
  handle_tr(policy_node, preshift, ret, properties)
28
27
 
29
- properties.build_event(
30
- policy_node,
31
- ret,
32
- preshift.object,
33
- ret,
34
- preshift.args,
35
- 1)
28
+ properties.build_event(policy_node, ret, preshift.object, ret, preshift.args, 1)
36
29
  ret
37
30
  end
38
31
 
@@ -43,12 +36,7 @@ module Contrast
43
36
  source = preshift.object
44
37
  args = preshift.args
45
38
  properties.splat_from(source, ret)
46
- properties.build_event(
47
- patcher,
48
- ret,
49
- source,
50
- ret,
51
- args)
39
+ properties.build_event(patcher, ret, source, ret, args)
52
40
  ret
53
41
  end
54
42
 
@@ -72,7 +60,7 @@ module Contrast
72
60
  end
73
61
 
74
62
  # Otherwise, we need to target each insertion point. Based on the spec for #tr & #tr_s, the find is
75
- # treated as a regex range, excepting the `\` character, which we'll need to escape. This converts to
63
+ # treated as a regexp range, excepting the `\` character, which we'll need to escape. This converts to
76
64
  # that form, wrapping the input in `[]`.
77
65
  find_string = preshift.args[0]
78
66
  find_string += '\\' if find_string.end_with?('\\')
@@ -1,6 +1,8 @@
1
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
+ return unless RUBY_VERSION < '2.6.0' # TODO: RUBY-714 remove guard w/ EOL of 2.5
5
+
4
6
  require 'contrast/agent/patching/policy/patch_status'
5
7
  require 'contrast/agent/module_data'
6
8
  require 'contrast/agent/rewriter'
@@ -41,7 +43,9 @@ module Contrast
41
43
  module_name = mod.cs__name
42
44
  return unless module_name
43
45
 
44
- if module_name.start_with?(Contrast::Utils::ObjectShare::CONTRAST_MODULE_START, Contrast::Utils::ObjectShare::ANONYMOUS_CLASS_MARKER)
46
+ if module_name.start_with?(Contrast::Utils::ObjectShare::CONTRAST_MODULE_START,
47
+ Contrast::Utils::ObjectShare::ANONYMOUS_CLASS_MARKER)
48
+
45
49
  status.no_rewrite!
46
50
  return
47
51
 
@@ -64,8 +68,7 @@ module Contrast
64
68
  # To get around this, we have those methods tell us the class
65
69
  # isn't ready
66
70
  def mid_defining? mod
67
- mod.instance_variable_defined?(:@cs__defining_class) &&
68
- mod.instance_variable_get(:@cs__defining_class)
71
+ mod.instance_variable_defined?(:@cs__defining_class) && mod.instance_variable_get(:@cs__defining_class)
69
72
  end
70
73
 
71
74
  def agent_should_rewrite?
@@ -56,7 +56,8 @@ module Contrast
56
56
  # double check that we were able to finalize the replaced return
57
57
  return unless Contrast::Agent::Assess::Tracker.trackable?(target)
58
58
  end
59
- apply_source(Contrast::Agent::REQUEST_TRACKER.current, source_node, target, object, ret, source_node.type, nil, *args)
59
+ apply_source(Contrast::Agent::REQUEST_TRACKER.current, source_node, target, object, ret,
60
+ source_node.type, nil, *args)
60
61
  restore_frozen_state ? ret : nil
61
62
  end
62
63
 
@@ -88,7 +89,9 @@ module Contrast
88
89
  # While we don't taint arrays themselves, we may taint the things they hold. Let's pass their keys and
89
90
  # values back to ourselves and try again
90
91
  elsif Contrast::Utils::DuckUtils.iterable_enumerable?(target)
91
- target.each { |value| apply_source(context, source_node, value, object, ret, source_type, source_name, *args) }
92
+ target.each do |value|
93
+ apply_source(context, source_node, value, object, ret, source_type, source_name, *args)
94
+ end
92
95
  end
93
96
  rescue StandardError => e
94
97
  logger.warn('Unable to apply source', e, node_id: source_node.id)
@@ -169,10 +172,7 @@ module Contrast
169
172
  length = Contrast::Utils::StringUtils.ret_length(target)
170
173
  properties.add_tag(tag, 0...length)
171
174
  properties.add_properties(source_node.properties)
172
- logger.trace('Source detected',
173
- node_id: source_node.id,
174
- target_id: target.__id__,
175
- tag: tag)
175
+ logger.trace('Source detected', node_id: source_node.id, target_id: target.__id__, tag: tag)
176
176
  end
177
177
  # make a representation of this method that TeamServer can render
178
178
  properties.build_event(source_node, target, object, ret, args, source_type, source_name)
@@ -11,9 +11,7 @@ module Contrast
11
11
  # certain tags in a given context. This provides a single place from
12
12
  # which those validations can be called.
13
13
  module SourceValidation
14
- VALIDATORS = [
15
- Contrast::Agent::Assess::Policy::SourceValidation::CrossSiteValidator
16
- ].cs__freeze
14
+ VALIDATORS = [Contrast::Agent::Assess::Policy::SourceValidation::CrossSiteValidator].cs__freeze
17
15
 
18
16
  # Determines if the conditions in which this source was called are
19
17
  # valid and should result in the application of a tag
@@ -44,7 +44,11 @@ module Contrast
44
44
  end
45
45
 
46
46
  if Contrast::Agent::Assess::Tracker.tracked?(ret)
47
- Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node, ret, erb_template_prerender, ret, interpolated_inputs)
47
+ Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node,
48
+ ret,
49
+ erb_template_prerender,
50
+ ret,
51
+ interpolated_inputs)
48
52
  end
49
53
 
50
54
  ret
@@ -42,18 +42,10 @@ module Contrast
42
42
  if trigger_node.sources&.any?
43
43
  trigger_node.sources.each do |marker|
44
44
  source = determine_source(marker, object, ret, args)
45
- apply_trigger(trigger_node,
46
- source,
47
- object,
48
- ret,
49
- *args)
45
+ apply_trigger(trigger_node, source, object, ret, *args)
50
46
  end
51
47
  else
52
- apply_trigger(trigger_node,
53
- nil,
54
- object,
55
- ret,
56
- *args)
48
+ apply_trigger(trigger_node, nil, object, ret, *args)
57
49
  end
58
50
  end
59
51
 
@@ -87,10 +79,8 @@ module Contrast
87
79
  append_route(finding, request)
88
80
  append_hash(finding, source, request)
89
81
  finding.version = determine_compliance_version(finding)
90
- logger.trace('Finding created',
91
- node_id: trigger_node.id,
92
- source_id: source.__id__,
93
- rule: trigger_node.rule_id)
82
+ logger.trace('Finding created', node_id: trigger_node.id, source_id: source.__id__,
83
+ rule: trigger_node.rule_id)
94
84
  report_finding(finding, request)
95
85
  rescue StandardError => e
96
86
  logger.error('Unable to build a finding', e, rule: trigger_node.rule_id, node_id: trigger_node.id)
@@ -285,7 +275,8 @@ module Contrast
285
275
 
286
276
  def append_events finding, trigger_node, source, object, ret, args
287
277
  append_from_source(finding, source)
288
- finding.events << Contrast::Agent::Assess::Events::EventFactory.build(trigger_node, source, object, ret, args).to_dtm_event
278
+ finding.events << Contrast::Agent::Assess::Events::EventFactory.build(trigger_node, source, object, ret,
279
+ args).to_dtm_event
289
280
  end
290
281
 
291
282
  def append_from_source finding, source
@@ -104,7 +104,8 @@ module Contrast
104
104
 
105
105
  properties = Contrast::Agent::Assess::Tracker.properties(source)
106
106
  # find the ranges that violate the rule (untrusted, etc)
107
- vulnerable_ranges = ranges_with_all_tags(Contrast::Utils::StringUtils.ret_length(source), properties, required_tags)
107
+ vulnerable_ranges = ranges_with_all_tags(Contrast::Utils::StringUtils.ret_length(source), properties,
108
+ required_tags)
108
109
  # if there aren't any vulnerable ranges, nope out
109
110
  return false if vulnerable_ranges.empty?
110
111
 
@@ -35,9 +35,10 @@ module Contrast
35
35
  # https://bitbucket.org/contrastsecurity/assess-specifications/src/master/rules/dataflow/redos.md
36
36
  def regexp_vulnerable? regexp
37
37
  # A pattern is considered vulnerable if it has 2 or more levels of nested multi-matching.
38
- # A level is defined as any set of opening and closing control characters immediately followed by a multi match control character.
39
- # A control character is defined as one of the OPENING_CHARS, CLOSING_CHARS,
40
- # or MULTI_MATCH_CHARS that is not immediately preceded by an escaping \ character.
38
+ # A level is defined as any set of opening and closing control characters immediately followed by a
39
+ # multi match control character.
40
+ # A control character is defined as one of the OPENING_CHARS, CLOSING_CHARS, or MULTI_MATCH_CHARS that
41
+ # is not immediately preceded by an escaping \ character.
41
42
  # OPENING_CHARS are ( and [ CLOSING_CHARS are ) and ] MULTI_MATCH_CHARS are +, *, and ?
42
43
 
43
44
  # Nota bene about Regexp#to_s: it doesn't necessarily give you the original Regexp back
@@ -10,8 +10,7 @@ module Contrast
10
10
  # before serializing that finding as a DTM to report to the service.
11
11
  module SSRFValidator
12
12
  RULE_NAME = 'ssrf'
13
- URL_PATTERN =
14
- %r{(?<protocol>http|https|ftp|sftp|telnet|gopher|rtsp|rtsps|ssh|svn)://(?<host>[^/?]+)(?<path>/?[^?]*)(?<query_string>\?.*)?}i.cs__freeze
13
+ URL_PATTERN = %r{(?<protocol>http|https|ftp|sftp|telnet|gopher|rtsp|rtsps|ssh|svn)://(?<host>[^/?]+)(?<path>/?[^?]*)(?<query_string>\?.*)?}i.cs__freeze # rubocop:disable Layout/LineLength
15
14
  # The Net::HTTP class validates host format on instantiation. Since
16
15
  # our triggers for that class are on the instance, they already
17
16
  # have this validation done for them. We do not need to apply the
@@ -11,14 +11,7 @@ module Contrast
11
11
  # the service.
12
12
  module XSSValidator
13
13
  RULE_NAME = 'reflected-xss'
14
- SAFE_CONTENT_TYPES = %w[
15
- /csv
16
- /javascript
17
- /json
18
- /pdf
19
- /x-javascript
20
- /x-json
21
- ].cs__freeze
14
+ SAFE_CONTENT_TYPES = %w[/csv /javascript /json /pdf /x-javascript /x-json].cs__freeze
22
15
 
23
16
  # A finding is valid for XSS if the response type is not one of
24
17
  # those assumed to be safe
@@ -14,7 +14,7 @@ module Contrast
14
14
  # @attr_reader event [Contrast::Agent::Assess::ContrastEvent] the
15
15
  # latest event to track
16
16
  module Evented
17
- attr_accessor :event
17
+ attr_reader :event
18
18
 
19
19
  # Create a new event and add it to the event set.
20
20
  #
@@ -31,7 +31,8 @@ module Contrast
31
31
  # the key used to accessed if from a map or nil if a type like
32
32
  # BODY
33
33
  def build_event policy_node, tagged, object, ret, args, source_type = nil, source_name = nil
34
- @event = Contrast::Agent::Assess::Events::EventFactory.build(policy_node, tagged, object, ret, args, source_type, source_name)
34
+ @event = Contrast::Agent::Assess::Events::EventFactory.build(policy_node, tagged, object, ret, args,
35
+ source_type, source_name)
35
36
  report_sources(tagged, event)
36
37
  end
37
38
 
@@ -46,10 +47,12 @@ module Contrast
46
47
  return unless tagged && !tagged.to_s.empty?
47
48
  return unless event.cs__is_a?(Contrast::Agent::Assess::Events::SourceEvent)
48
49
  return unless event.source_type
50
+ return unless (current_request = Contrast::Agent::REQUEST_TRACKER.current)
51
+
52
+ if current_request.observed_route.sources.any? do |source|
53
+ source.type == event.forced_source_type && source.name == event.forced_source_name
54
+ end
49
55
 
50
- current_request = Contrast::Agent::REQUEST_TRACKER.current
51
- return unless current_request
52
- if current_request.observed_route.sources.any? { |source| source.type == event.forced_source_type && source.name == event.forced_source_name }
53
56
  return
54
57
  end
55
58
 
@@ -55,9 +55,12 @@ module Contrast
55
55
  value_node.children.each do |child|
56
56
  next unless child
57
57
 
58
- return false unless child.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) &&
59
- child.type == :LIT &&
60
- child.children[0]&.cs__is_a?(Integer)
58
+ unless child.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) &&
59
+ child.type == :LIT &&
60
+ child.children[0]&.cs__is_a?(Integer)
61
+
62
+ return false
63
+ end
61
64
  end
62
65
 
63
66
  true
@@ -84,8 +87,11 @@ module Contrast
84
87
  return false unless children.length >= 2
85
88
 
86
89
  potential_string_node = children[0]
87
- return false unless potential_string_node.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) &&
88
- potential_string_node.type == :STR
90
+ unless potential_string_node.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) &&
91
+ potential_string_node.type == :STR
92
+
93
+ return false
94
+ end
89
95
 
90
96
  children[1] == :bytes
91
97
  end
@@ -29,7 +29,10 @@ module Contrast
29
29
  # These are markers whose presence indicates that a field is more
30
30
  # likely to be a descriptor or requirement than an actual password.
31
31
  # We should ignore fields that contain them.
32
- NON_PASSWORD_PARTIAL_NAMES = %w[DATE FORGOT FORM ENCODE PATTERN PREFIX PROP SUFFIX URL BASE FILE URI].cs__freeze
32
+ NON_PASSWORD_PARTIAL_NAMES = %w[
33
+ DATE FORGOT FORM ENCODE PATTERN PREFIX PROP SUFFIX URL BASE FILE
34
+ URI
35
+ ].cs__freeze
33
36
 
34
37
  # If the constant looks like a password and it doesn't look like a
35
38
  # password descriptor, it passes for this rule
@@ -26,10 +26,7 @@ module Contrast
26
26
  end
27
27
 
28
28
  # TODO: RUBY-1014 - remove `#analyze`
29
- COMMON_CONSTANTS = %i[
30
- CONTRAST_ASSESS_POLICY_STATUS
31
- VERSION
32
- ].cs__freeze
29
+ COMMON_CONSTANTS = %i[CONTRAST_ASSESS_POLICY_STATUS VERSION].cs__freeze
33
30
  def analyze clazz
34
31
  return if disabled?
35
32
 
@@ -171,7 +168,8 @@ module Contrast
171
168
 
172
169
  finding.properties[SOURCE_KEY] = Contrast::Utils::StringUtils.protobuf_safe_string(class_name)
173
170
  finding.properties[CONSTANT_NAME_KEY] = Contrast::Utils::StringUtils.protobuf_safe_string(constant_string)
174
- finding.properties[CODE_SOURCE_KEY] = Contrast::Utils::StringUtils.protobuf_safe_string(constant_string + redacted_marker)
171
+ finding.properties[CODE_SOURCE_KEY] =
172
+ Contrast::Utils::StringUtils.protobuf_safe_string(constant_string + redacted_marker)
175
173
 
176
174
  hash = Contrast::Utils::HashDigest.generate_class_scanning_hash(finding)
177
175
  finding.hash_code = Contrast::Utils::StringUtils.protobuf_safe_string(hash)
@@ -1,6 +1,8 @@
1
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
+ return unless RUBY_VERSION < '2.6.0' # TODO: RUBY-714 remove guard w/ EOL of 2.5
5
+
4
6
  require 'ripper'
5
7
  require 'contrast/extension/module'
6
8
  require 'contrast/components/interface'
@@ -48,7 +50,7 @@ module Contrast
48
50
  :public_instance_methods, :protected_instance_methods, :private_instance_methods, :locations
49
51
 
50
52
  def initialize module_data
51
- @class_module_path = module_data.name
53
+ @class_module_path = module_data.mod_name
52
54
  clazz = module_data.mod
53
55
  @is_class = clazz.is_a?(Class)
54
56
  @public_instance_methods = []
@@ -13,9 +13,7 @@ module Contrast
13
13
  access_component :agent, :logging
14
14
 
15
15
  def self.run _reaction, level
16
- logger.with_level(
17
- level,
18
- 'Contrast received instructions to disable itself - Disabling now')
16
+ logger.with_level(level, 'Contrast received instructions to disable itself - Disabling now')
19
17
  AGENT.disable!
20
18
  end
21
19
  end
@@ -47,7 +47,7 @@ module Contrast
47
47
  return if @wildcard_url
48
48
  return unless @exclusion.urls&.any?
49
49
 
50
- @wildcard_url ||= @exclusion.urls.any? { |test| test == '/.*' }
50
+ @wildcard_url ||= @exclusion.urls.any?('/.*')
51
51
  return if @wildcard_url
52
52
 
53
53
  @urls = []
@@ -95,8 +95,8 @@ module Contrast
95
95
  @exclusion.type == Contrast::Api::Settings::Exclusion::ExclusionType::CODE
96
96
  end
97
97
 
98
- def name
99
- @exclusion.name
98
+ def exc_name
99
+ @exclusion.name # rubocop:disable Security/Module/Name -- part of the API.
100
100
  end
101
101
 
102
102
  def match_all?
@@ -109,10 +109,7 @@ module Contrast
109
109
  #
110
110
  # @param rule - the id of the rule which we're checking for exclusion
111
111
  def protection_rule? rule
112
- protect? &&
113
- (@exclusion.protection_rules.empty? ||
114
- @exclusion.protection_rules.include?(rule)
115
- )
112
+ protect? && (@exclusion.protection_rules.empty? || @exclusion.protection_rules.include?(rule))
116
113
  end
117
114
 
118
115
  # Determine if the given rule is excluded by this exclusion.
@@ -121,10 +118,7 @@ module Contrast
121
118
  #
122
119
  # @param rule - the id of the rule which we're checking for exclusion
123
120
  def assess_rule? rule
124
- assess? &&
125
- (@exclusion.assessment_rules.empty? ||
126
- @exclusion.assessment_rules.include?(rule)
127
- )
121
+ assess? && (@exclusion.assessment_rules.empty? || @exclusion.assessment_rules.include?(rule))
128
122
  end
129
123
 
130
124
  def match_code? stack_trace
@@ -33,6 +33,7 @@ module Contrast
33
33
  # then contrast depends on it. If its array of dependents is 1, then contrast is the
34
34
  # only dependency in that list. Since only contrast depends on it, we should ignore it.
35
35
  def find_contrast_gems
36
+ # rubocop:disable Security/Module/Name -- here name is part of Ruby Gems.
36
37
  ignore = Set.new([CONTRAST_AGENT])
37
38
  contrast_specs = Gem::DependencyList.from_specs.specs.find do |dependency|
38
39
  dependency.name == CONTRAST_AGENT
@@ -43,6 +44,7 @@ module Contrast
43
44
  ignore.add(dependency.name) if contrast_dep_set.include?(dependency.name) && dependents.length == 1
44
45
  end
45
46
  ignore
47
+ # rubocop:enable Security/Module/Name
46
48
  end
47
49
  end
48
50
  end
@@ -37,9 +37,8 @@ module Contrast
37
37
  @app = app # THIS MUST BE FIRST AND ALWAYS SET!
38
38
  setup_agent # THIS MUST BE SECOND AND ALWAYS CALLED!
39
39
  unless AGENT.enabled?
40
- logger.error(
41
- 'The Agent was unable to initialize before the application middleware was initialized. ' \
42
- 'Disabling permanently.')
40
+ logger.error('The Agent was unable to initialize before the application middleware was initialized. '\
41
+ 'Disabling permanently.')
43
42
  AGENT.disable! # ensure the agent is disabled (probably redundant)
44
43
  return
45
44
  end
@@ -207,8 +206,7 @@ module Contrast
207
206
  # @param exception [Exception]
208
207
  # @return [Boolean]
209
208
  def security_exception? exception
210
- exception.is_a?(Contrast::SecurityException) ||
211
- exception.message&.include?(SECURITY_EXCEPTION_MARKER)
209
+ exception.is_a?(Contrast::SecurityException) || exception.message&.include?(SECURITY_EXCEPTION_MARKER)
212
210
  end
213
211
 
214
212
  # As we deprecate support to prepare to remove dead code, we need to inform our users still relying on the now