ALL-SECU0002 · weak_hashing_primitive
Count the calls that reach a hash primitive the world already knows how to break.
This is a deterministic rule for all languages. Read its implementation.
Definition
Section titled “Definition”Read every call a declaration states and report one that reaches MD5, SHA-1, or another digest
with a published collision. Most languages carry the primitive in the callee name and a
factory carries it in the literal handed to the call, so both are read and one rule answers
for hashlib.md5, MD5.Create, Md5::new, and createHash('md5'). A broken digest is
expensive the moment it ships, because a collision lets someone swap the content behind a
signature that still verifies, and every artifact already signed with it has to be signed
again by hand.
Evidence
Section titled “Evidence”Each finding names the declaration, the call, and the line. The value is how many calls reach
a broken primitive. A nested call keeps its own node, so outer(md5(data)) is read once.
Exceptions
Section titled “Exceptions”A digest that guards nothing, such as a cache key or a shard bucket, costs nothing when it
collides, so a call that states it is not used for security is left alone. A project that
wraps its own name around a broken primitive names that wrapper through also_broken, since
no list of spellings is ever finished. The factories setting names call spellings whose
literal arguments carry the primitive rather than the callee itself.
Examples
Section titled “Examples”signature = hashlib.md5(payload).hexdigest()signature = hashlib.sha256(payload).hexdigest()References
Section titled “References”- Generalizes Ruff S324 hashlib-insecure-hash-function. Open reference
- Cites “Common Weakness Enumeration”, CWE-327, use of a broken or risky cryptographic algorithm. Open reference
- Cites “The First Collision for Full SHA-1”. Open reference