Hashing data is security-sensitive. It has led in the past to the following vulnerabilities:

Cryptographic hash functions are used to uniquely identify information without storing their original form. When not done properly, an attacker can steal the original information by guessing it (ex: with a rainbow table), or replace the original data with another one having the same hash.

This rule flags code that initiates hashing.

Ask Yourself Whether

You are at risk if you answered yes to the first question and any of the following ones.

Recommended Secure Coding Practices

Sensitive Code Example

hashlib module

import hashlib

def hash_data(algorithm):
    hashlib.new(algorithm)  # Sensitive

    hashlib.blake2b  # Sensitive
    hashlib.blake2s  # Sensitive
    hashlib.md5  # Sensitive
    hashlib.pbkdf2_hmac # Sensitive
    hashlib.sha1  # Sensitive
    hashlib.sha224  # Sensitive
    hashlib.sha256  # Sensitive
    hashlib.sha384  # Sensitive
    hashlib.sha3_224  # Sensitive
    hashlib.sha3_256  # Sensitive
    hashlib.sha3_384  # Sensitive
    hashlib.sha3_512  # Sensitive
    hashlib.sha512  # Sensitive
    hashlib.shake_128  # Sensitive
    hashlib.shake_256  # Sensitive
    hashlib.scrypt  # Sensitive

cryptography library

from cryptography.hazmat.primitives import hashes


def my_hash(algorithm):
    hashes.Hash(algorithm)  # Sensitive

Django

from django.contrib.auth.hashers import PBKDF2PasswordHasher, PBKDF2SHA1PasswordHasher, Argon2PasswordHasher, \
    BCryptSHA256PasswordHasher, BasePasswordHasher, BCryptPasswordHasher, SHA1PasswordHasher, MD5PasswordHasher, \
    UnsaltedSHA1PasswordHasher, UnsaltedMD5PasswordHasher, CryptPasswordHasher

from django.contrib.auth.hashers import make_password

# Changing default hashers

from django.conf import settings

def update_settings(value):
    settings.PASSWORD_HASHERS = value  # Sensitive, and also a bad practice


# Creating custom Hasher

class MyBasePasswordHasher(BasePasswordHasher):  # Sensitive
    pass

class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):  # Sensitive
    pass

class MyPBKDF2SHA1PasswordHasher(PBKDF2SHA1PasswordHasher):  # Sensitive
    pass

class MyArgon2PasswordHasher(Argon2PasswordHasher):  # Sensitive
    pass

class MyBCryptSHA256PasswordHasher(BCryptSHA256PasswordHasher):  # Sensitive
    pass

class MyBCryptPasswordHasher(BCryptPasswordHasher):  # Sensitive
    pass

class MySHA1PasswordHasher(SHA1PasswordHasher):  # Sensitive
    pass

class MyMD5PasswordHasher(MD5PasswordHasher):  # Sensitive
    pass

class MyUnsaltedSHA1PasswordHasher(UnsaltedSHA1PasswordHasher):  # Sensitive
    pass

class MyUnsaltedMD5PasswordHasher(UnsaltedMD5PasswordHasher):  # Sensitive
    pass

class MyCryptPasswordHasher(CryptPasswordHasher):  # Sensitive
    pass


# Calling make_password with a specific hasher name or salt should be reviewed
def my_make_password(password, salt, hasher):
    make_password(password, salt=salt)  # Sensitive
    make_password(password, hasher=hasher)  # Sensitive
    make_password(password, salt=salt, hasher=hasher)  # Sensitive

    # No issue is raised when only the password is provided, then only the configuration should be reviewed
    make_password(password)  # OK

Django's "global_settings.py" configuration file

# NOTE: The following code raises issues only if the file is named "global_settings.py". This is the default
# name of Django configuration file

PASSWORD_HASHERS=[]  # Sensitive

Werkzeug

from werkzeug.security import generate_password_hash

def hash_password(password):
    generate_password_hash(password)  # Sensitive

passlib module

import passlib.hash

passlib.hash.apr_md5_crypt  # Sensitive
passlib.hash.argon2  # Sensitive
passlib.hash.atlassian_pbkdf2_sha1  # Sensitive
passlib.hash.bcrypt  # Sensitive
passlib.hash.bcrypt_sha256  # Sensitive
passlib.hash.bigcrypt  # Sensitive
passlib.hash.bsd_nthash  # Sensitive
passlib.hash.bsdi_crypt  # Sensitive
passlib.hash.cisco_asa  # Sensitive
passlib.hash.cisco_pix  # Sensitive
passlib.hash.cisco_type7  # Sensitive
passlib.hash.crypt16  # Sensitive
passlib.hash.cta_pbkdf2_sha1  # Sensitive
passlib.hash.des_crypt  # Sensitive
passlib.hash.django_argon2  # Sensitive
passlib.hash.django_bcrypt  # Sensitive
passlib.hash.django_bcrypt_sha256  # Sensitive
passlib.hash.django_des_crypt  # Sensitive
passlib.hash.django_disabled  # Sensitive
passlib.hash.django_pbkdf2_sha1  # Sensitive
passlib.hash.django_pbkdf2_sha256  # Sensitive
passlib.hash.django_salted_md5  # Sensitive
passlib.hash.django_salted_sha1  # Sensitive
passlib.hash.dlitz_pbkdf2_sha1  # Sensitive
passlib.hash.fshp  # Sensitive
passlib.hash.grub_pbkdf2_sha512  # Sensitive
passlib.hash.hex_md4  # Sensitive
passlib.hash.hex_md5  # Sensitive
passlib.hash.hex_sha1  # Sensitive
passlib.hash.hex_sha256  # Sensitive
passlib.hash.hex_sha512  # Sensitive
passlib.hash.htdigest  # Sensitive
passlib.hash.ldap_bcrypt  # Sensitive
passlib.hash.ldap_bsdi_crypt  # Sensitive
passlib.hash.ldap_des_crypt  # Sensitive
passlib.hash.ldap_hex_md5  # Sensitive
passlib.hash.ldap_hex_sha1  # Sensitive
passlib.hash.ldap_md5  # Sensitive
passlib.hash.ldap_md5_crypt  # Sensitive
passlib.hash.ldap_pbkdf2_sha1  # Sensitive
passlib.hash.ldap_pbkdf2_sha256  # Sensitive
passlib.hash.ldap_pbkdf2_sha512  # Sensitive
passlib.hash.ldap_plaintext  # Sensitive
passlib.hash.ldap_salted_md5  # Sensitive
passlib.hash.ldap_salted_sha1  # Sensitive
passlib.hash.ldap_sha1  # Sensitive
passlib.hash.ldap_sha1_crypt  # Sensitive
passlib.hash.ldap_sha256_crypt  # Sensitive
passlib.hash.ldap_sha512_crypt  # Sensitive
passlib.hash.lmhash  # Sensitive
passlib.hash.md5_crypt  # Sensitive
passlib.hash.msdcc  # Sensitive
passlib.hash.msdcc2  # Sensitive
passlib.hash.mssql2000  # Sensitive
passlib.hash.mssql2005  # Sensitive
passlib.hash.mysql323  # Sensitive
passlib.hash.mysql41  # Sensitive
passlib.hash.nthash  # Sensitive
passlib.hash.oracle10  # Sensitive
passlib.hash.oracle11  # Sensitive
passlib.hash.pbkdf2_sha1  # Sensitive
passlib.hash.pbkdf2_sha256  # Sensitive
passlib.hash.pbkdf2_sha512  # Sensitive
passlib.hash.phpass  # Sensitive
passlib.hash.plaintext  # Sensitive
passlib.hash.postgres_md5  # Sensitive
passlib.hash.roundup_plaintext  # Sensitive
passlib.hash.scram  # Sensitive
passlib.hash.scrypt  # Sensitive
passlib.hash.sha1_crypt  # Sensitive
passlib.hash.sha256_crypt  # Sensitive
passlib.hash.sha512_crypt  # Sensitive
passlib.hash.sun_md5_crypt  # Sensitive
passlib.hash.unix_disabled  # Sensitive
passlib.hash.unix_fallback  # Sensitive

pynacl library

import nacl.pwhash
from nacl.pwhash.argon2i import str as argon2i_str, kdf as argon2i_kdf
from nacl.pwhash.argon2id import str as argon2id_str, kdf as argon2id_kdf
from nacl.pwhash.scrypt import str as scrypt_str, kdf as scrypt_kdf

from nacl.hash import blake2b, sha256, sha512

blake2b  # Sensitive
sha256  # Sensitive
sha512  # Sensitive

nacl.pwhash.str  # Sensitive
nacl.pwhash.scryptsalsa208sha256_str  # Sensitive
nacl.pwhash.kdf_scryptsalsa208sha256  # Sensitive
nacl.pwhash.argon2id.str  # Sensitive
nacl.pwhash.argon2i.str  # Sensitive
nacl.pwhash.scrypt.str  # Sensitive
nacl.pwhash.argon2id.kdf  # Sensitive
nacl.pwhash.argon2i.kdf  # Sensitive
nacl.pwhash.scrypt.kdf  # Sensitive

argon2i_str  # Sensitive
argon2id_str  # Sensitive
scrypt_str  # Sensitive
argon2i_kdf  # Sensitive
argon2id_kdf  # Sensitive
scrypt_kdf  # Sensitive

See