lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb in contrast-agent-4.14.1 vs lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb in contrast-agent-5.0.0

- old
+ new

@@ -1,6 +1,6 @@ -# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. +# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/agent/assess/policy/trigger_method' require 'contrast/components/logger' require 'contrast/extension/module' @@ -23,57 +23,10 @@ def disabled? !::Contrast::ASSESS.enabled? || ::Contrast::ASSESS.rule_disabled?(rule_id) end - # TODO: RUBY-1014 - remove `#analyze` - COMMON_CONSTANTS = %i[CONTRAST_ASSESS_POLICY_STATUS VERSION].cs__freeze - def analyze clazz - return if disabled? - - # we only want the constants explicitly defined in this class, not - # those of its ancestor(s) - constants = clazz.cs__constants(false) - - # if there are no constants, let's just leave - return unless constants&.any? - - constants.each do |constant| - next if COMMON_CONSTANTS.include?(constant) - - # if this class autoloads its constant, get the hell away from it - # I mean it! Don't even think about it. - # - # Autoload means this constant (usually [always?] a class or - # module) won't be required until something in the application - # tries to load it. We CANNOT be that thing. We'll just have to - # wait until it's loaded, at which point we'll be handed it - # again. - next if clazz.cs__autoload?(constant) - - # constant comes to us as a symbol. that sucks. we need to do - # some string methods on it, so stringify it. - constant_string = constant.to_s - - # if this is another class or a module, move on - next unless constant_name?(constant_string) - - next unless name_passes?(constant_string) - - value = clazz.cs__const_get(constant, false) - - # if the constant isn't holding a string, skip it - next unless value_type_passes?(value) - - # if it looks like a placeholder / pointer to a config, skip it - next unless value_passes?(value) - - new_finding_and_reporting clazz, constant_string - build_finding clazz, constant_string - end - end - # Parse the file pertaining to the given TracePoint to walk its AST # to determine if a Constant is hardcoded. For our purposes, this # hard coding means directly set rather than as an interpolated # String or through a method call. # @@ -91,18 +44,10 @@ parse_ast(trace_point.self, ast) rescue StandardError => e logger.error('Unable to parse AST for hardcoded keys', e, module: trace_point.self) end - # Constants can be variable or classes defined in the given - # class. We ONLY want the variables, which should be defined in - # the MACRO_CASE (upper case & underscore format) - CONSTANT_NAME_PATTERN = /^[A-Z_]+$/.cs__freeze - def constant_name? constant - constant.match?(CONSTANT_NAME_PATTERN) - end - # The name of the field CONSTANT_NAME_KEY = 'name' # The code line, recreated, with the password obfuscated CODE_SOURCE_KEY = 'codeSource' # The constant name @@ -138,12 +83,15 @@ value = children[1] # The assignment node could be a direct value or a call of some # sort. We leave it to each rule to properly handle these nodes. return unless value_node_passes?(value) - new_finding_and_reporting mod, name - build_finding mod, name + if Contrast::Agent::Reporter.enabled? + new_finding_and_reporting mod, name + else # TODO: RUBY-1438 -- remove + build_finding mod, name + end end # Constants can be set as frozen directly. We need to account for # this change as it means the Node given to the :CDECL call will be # a :CALL, not a constant. @@ -208,10 +156,10 @@ save_and_report_finding ruby_finding, new_preflight end def save_and_report_finding ruby_finding, new_preflight Contrast::Agent::Reporting::ReportingStorage[hash] = ruby_finding - Contrast::Agent.reporter_queue.send_event_immediately(new_preflight) + Contrast::Agent.reporter&.send_event_immediately(new_preflight) end end end end end