Class: Scryer::Rules::WeakCryptoRule
- Inherits:
-
Scryer::Rule
- Object
- Scryer::Rule
- Scryer::Rules::WeakCryptoRule
- Defined in:
- lib/scryer/rules/weak_crypto_rule.rb
Overview
Flags Digest::MD5/Digest::SHA1 used in a context that looks like
password/credential hashing (method or nearby variable name contains
"password"/"passwd") — both are cryptographically broken for that use
case; a fast general-purpose hash lets an attacker who steals the DB
brute-force passwords far faster than a proper password hash
(bcrypt/scrypt/argon2, which are deliberately slow).
Constant Summary collapse
- WEAK_DIGESTS =
%w[MD5 SHA1].freeze
- PASSWORD_HINT =
/password|passwd|credential/i.freeze
Instance Attribute Summary
Attributes inherited from Scryer::Rule
Instance Method Summary collapse
Methods inherited from Scryer::Rule
Constructor Details
This class inherits a constructor from Scryer::Rule
Instance Method Details
#scan ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/scryer/rules/weak_crypto_rule.rb', line 18 def scan findings = [] Ast.each_node(sexp) do |node| next unless Ast.tagged?(node, :top_const_ref, :const_path_ref, :var_ref) digest_name = digest_algorithm_name(node) next unless digest_name # Only flag when something nearby (same statement/line) mentions # password-ish naming — Digest::MD5/SHA1 have plenty of legitimate # non-credential uses (cache keys, ETags, checksums) that shouldn't # be flagged as a crypto weakness. line = Ast.line_of(node) context_line = Ast.source_line(source, line).to_s next unless PASSWORD_HINT.match?(context_line) findings << finding( line: line, message: "`Digest::#{digest_name}` is used near what looks like password/credential " \ "handling — #{digest_name} is fast and unsalted by default, making stolen " \ "hashes practical to brute-force.", suggested_fix: "Use `bcrypt` via Rails' `has_secure_password` for password storage " \ "instead of a general-purpose digest — it's deliberately slow and " \ "handles salting automatically. Reserve Digest::#{digest_name} for " \ "non-credential uses (cache keys, checksums)." ) end findings end |