Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.
Why this matters
A CryptContext lists a password hashing scheme that is broken for storing credentials: unsalted or fast digests (hex_md5, hex_sha1, hex_sha256, md5_crypt, ldap_md5), legacy des_crypt, or outright plaintext / ldap_plaintext. These are trivially brute-forced or reversed, so any leaked hash exposes the underlying password (CWE-916).
Use a slow, salted, memory-hard scheme as the default, e.g. CryptContext(schemes=["argon2"]) or CryptContext(schemes=["bcrypt"]). Keep a weak scheme only as a deprecated verifier during migration, never as an active hashing scheme.
VULNERABLE
vulnerable.py
from passlib.context import CryptContext# ruleid: auth.py.crypto.passlib-weak-schemepwd_context = CryptContext(schemes=["md5_crypt"], deprecated="auto")# ruleid: auth.py.crypto.passlib-weak-schemeplain_context = CryptContext(schemes=["plaintext"])# Weak digest scheme mixed into the list.# ruleid: auth.py.crypto.passlib-weak-schememixed_context = CryptContext(schemes=["hex_sha1", "des_crypt"])# ruleid: auth.py.crypto.passlib-weak-schemeldap_context = CryptContext(schemes=["ldap_plaintext"], deprecated="auto")
SAFE
safe.py
from passlib.context import CryptContext# ok: auth.py.crypto.passlib-weak-schemebcrypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")# ok: auth.py.crypto.passlib-weak-schemeargon2_context = CryptContext(schemes=["argon2"])# Modern schemes only; "sha256_crypt" must not match the "hex_sha256" entry.# ok: auth.py.crypto.passlib-weak-schemestrong_context = CryptContext(schemes=["argon2", "pbkdf2_sha256", "sha256_crypt"])
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.