Class: Contrast::Agent::Assess::Rule::Provider::HardcodedPassword

Inherits:
Object
  • Object
show all
Includes:
HardcodedValueRule
Defined in:
lib/contrast/agent/assess/rule/provider/hardcoded_password.rb

Overview

Determine if there are any passwords hardcoded into the sourcecode of the application. A constant is a password if: 1) the name contains a PASSWORD_FIELD_NAMES value 2) the name does not contain a NON_PASSWORD_PARTIAL_NAMES value 3) the value is a String 4) the value is not solely alphanumeric and ‘.’ or ‘_’ * note that

mixing the characters counts as a violation of this rule

Constant Summary collapse

NAME =
'hardcoded-password'
REDACTED_MARKER =
' = "**REDACTED**"'
PROPERTY_NAME_PATTERN =
/^[a-z]+[._][._a-z]*[a-z]+$/.cs__freeze
PASSWORD_FIELD_NAMES =

These are names, determined by the security team (Matt & Ar), that indicate a field is likely to be a password or secret token of some sort.

%w[PASSWORD PASSKEY PASSPHRASE SECRET].cs__freeze
NON_PASSWORD_PARTIAL_NAMES =

These are markers whose presence indicates that a field is more likely to be a descriptor or requirement than an actual password. We should ignore fields that contain them.

%w[
  DATE FORGOT FORM ENCODE PATTERN PREFIX PROP SUFFIX URL BASE FILE
  URI
].cs__freeze

Constants included from HardcodedValueRule

Contrast::Agent::Assess::Rule::Provider::HardcodedValueRule::CODE_SOURCE_KEY, Contrast::Agent::Assess::Rule::Provider::HardcodedValueRule::CONSTANT_NAME_KEY, Contrast::Agent::Assess::Rule::Provider::HardcodedValueRule::SOURCE_KEY

Instance Method Summary collapse

Methods included from HardcodedValueRule

#disabled?, #parse

Methods included from Components::Logger::InstanceMethods

#cef_logger, #logger

Instance Method Details

#name_passes?(constant_string) ⇒ Boolean

If the constant looks like a password and it doesn’t look like a password descriptor, it passes for this rule

Returns:

  • (Boolean)


40
41
42
43
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_password.rb', line 40

def name_passes? constant_string
  PASSWORD_FIELD_NAMES.any? { |name| constant_string.index(name) } &&
      NON_PASSWORD_PARTIAL_NAMES.none? { |name| constant_string.index(name) }
end

#probably_property_name?(value) ⇒ Boolean

If a field name matches an expected password field, we’ll check it’s value to see if it looks like a placeholder. For our purposes, placeholders will be any non-empty String conforming to the patterns below. We do combine the patterns with [._] as in Ruby these two characters are probably more likely to appear together in a default placeholder than in a password. Note this is opposite of the behavior in Java

Returns:

  • (Boolean)


66
67
68
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_password.rb', line 66

def probably_property_name? value
  value.match?(PROPERTY_NAME_PATTERN)
end

#redacted_markerObject



70
71
72
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_password.rb', line 70

def redacted_marker
  REDACTED_MARKER
end

#rule_idObject



34
35
36
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_password.rb', line 34

def rule_id
  NAME
end

#value_node_passes?(value_node) ⇒ Boolean

Determine if the given value node violates the hardcode key rule

Parameters:

  • value_node (RubyVM::AbstractSyntaxTree::Node)

    the node to evaluate

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
57
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_password.rb', line 49

def value_node_passes? value_node
  # If it's a freeze call, then evaluate the entity being frozen
  value_node = value_node.children[0] if freeze_call?(value_node)
  return false unless value_node.type == :STR

  # https://www.rubydoc.info/gems/ruby-internal/Node/STR
  string = value_node.children[0]
  !probably_property_name?(string)
end