Class: Contrast::Agent::Assess::Rule::Provider::HardcodedKey
- Includes:
- HardcodedValueRule
- Defined in:
- lib/contrast/agent/assess/rule/provider/hardcoded_key.rb
Overview
Determine if there are any cryptographic keys hardcoded into the sourcecode of the application. A constant is a cryptographic key if: 1) the name contains a KEY_FIELD_NAME value 2) the value is a non-empty array of only Fixnums
Constant Summary collapse
- REDACTED_MARKER =
' = [**REDACTED**]'
- NAME =
'hardcoded-key'
- KEY_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[KEY AES DES IV SECRET].cs__freeze
- NON_KEY_PARTIAL_NAMES =
These are markers whose presence indicates that a field is more likely to be a descriptor or requirement than an actual key. We should ignore fields that contain them.
%w[CONTENT_CODES RESPONSE_CODES ERROR_CODES].cs__freeze
- BYTE_HOLDERS =
%i[ARRAY LIST].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
-
#bytes_call?(value_node) ⇒ Boolean
A node is a bytes_call if it’s the Node for String#bytes.
- #name_passes?(constant_string) ⇒ Boolean
- #redacted_marker ⇒ Object
- #rule_id ⇒ Object
-
#value_node_passes?(value_node) ⇒ Boolean
Determine if the given value node violates the hardcode key rule.
Methods included from HardcodedValueRule
Methods included from Components::Logger::InstanceMethods
Instance Method Details
#bytes_call?(value_node) ⇒ Boolean
A node is a bytes_call if it’s the Node for String#bytes. We care about this specifically as it’s likely to be a common way to generate a key constant, rather than directly declaring an integer array.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_key.rb', line 80 def bytes_call? value_node return false unless value_node.type == :CALL children = value_node.children return false unless children return false unless children.length >= 2 potential_string_node = children[0] unless potential_string_node.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) && potential_string_node.type == :STR return false end children[1] == :bytes end |
#name_passes?(constant_string) ⇒ Boolean
31 32 33 34 |
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_key.rb', line 31 def name_passes? constant_string KEY_FIELD_NAMES.any? { |name| constant_string.index(name) } && NON_KEY_PARTIAL_NAMES.none? { |name| constant_string.index(name) } end |
#redacted_marker ⇒ Object
68 69 70 |
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_key.rb', line 68 def redacted_marker REDACTED_MARKER end |
#rule_id ⇒ Object
27 28 29 |
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_key.rb', line 27 def rule_id NAME end |
#value_node_passes?(value_node) ⇒ Boolean
Determine if the given value node violates the hardcode key rule
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/contrast/agent/assess/rule/provider/hardcoded_key.rb', line 40 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) # If it's a String being turned into bytes, then it matches key # expectations return true if bytes_call?(value_node) type = value_node.type return false unless BYTE_HOLDERS.include?(type) return false unless value_node.children.any? # Unless this is an array of literal numerics, we don't match. # That array seems to always end in a nil value, so we allow # those as well. value_node.children.each do |child| next unless child unless child.cs__is_a?(RubyVM::AbstractSyntaxTree::Node) && child.type == :LIT && child.children[0]&.cs__is_a?(Integer) return false end end true end |