[Security] Fix CodeQL alert #16: Use of a broken or weak cryptographic hashing algorithm on sensitive data#90
Conversation
… hashing algorithm on sensitive data
|
|
||
| def hash_password_weak(password): | ||
| return hashlib.md5(password.encode()).hexdigest() | ||
| return hashlib.sha256(password.encode()).hexdigest() |
Check failure
Code scanning / CodeQL
Use of a broken or weak cryptographic hashing algorithm on sensitive data High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 months ago
In general, password hashing must use a dedicated, slow, memory-hard password hashing scheme such as Argon2, scrypt, bcrypt, or PBKDF2, rather than a fast general-purpose hash like SHA-256. These algorithms also incorporate salts and parameters (iterations, memory cost, parallelism) to make brute-force attacks impractical.
For this specific code, the minimal-impact fix is to change hash_password_weak to use a standard password hashing primitive while preserving the function’s interface (accept a plaintext password, return a string hash). A good choice with no extra application code is PBKDF2 via hashlib.pbkdf2_hmac, which is part of the Python standard library and thus doesn’t introduce nonstandard dependencies. To do this, we will:
- Add imports for
osandbase64at the top ofvulnerable_weak_crypto.py(or reuse them if already present) so we can generate a random salt and return a safe string representation. - Replace the body of
hash_password_weakto:- Generate a random 16-byte salt using
os.urandom(16). - Derive a 32-byte key using
hashlib.pbkdf2_hmac('sha256', password.encode(), salt, iterations), with a reasonable iteration count (for example, 100_000 as commonly recommended). - Encode the salt and derived key with
base64.b64encodeand join them with a separator (e.g.,"salt$hash") into a single string for storage/verification.
- Generate a random 16-byte salt using
- Leave the rest of the file (including other weak constructs) untouched, since the CodeQL finding we’re addressing specifically concerns the use of SHA-256 for password hashing at line 7.
This preserves the outward behavior (input: password string; output: hash string) while making the hashing algorithm computationally expensive and salted.
| @@ -2,9 +2,17 @@ | ||
| import random | ||
| from Crypto.Cipher import DES, ARC2, Blowfish | ||
| from Crypto.Hash import MD5, SHA1 | ||
| import os | ||
| import base64 | ||
|
|
||
| def hash_password_weak(password): | ||
| return hashlib.sha256(password.encode()).hexdigest() | ||
| # Use a computationally expensive, salted hash (PBKDF2) instead of raw SHA-256 | ||
| salt = os.urandom(16) | ||
| iterations = 100_000 | ||
| dk = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, iterations, dklen=32) | ||
| salt_b64 = base64.b64encode(salt).decode('ascii') | ||
| dk_b64 = base64.b64encode(dk).decode('ascii') | ||
| return f"{iterations}${salt_b64}${dk_b64}" | ||
|
|
||
| def hash_with_sha1(data): | ||
| return hashlib.sha1(data.encode()).hexdigest() |
There was a problem hiding this comment.
🔴 Hash algorithm mismatch between hash_password_weak (now SHA256) and verify_password (still MD5)
The PR updated hash_password_weak from MD5 to SHA256, but the corresponding verify_password function at vulnerable_weak_crypto.py:40 still uses hashlib.md5 to compute the hash for comparison. If a password is stored using hash_password_weak (SHA256) and later verified using verify_password (MD5), the hashes will never match, causing all password verifications to fail.
(Refers to line 40)
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
|
|
||
| def hash_password_weak(password): | ||
| return hashlib.md5(password.encode()).hexdigest() | ||
| return hashlib.sha256(password.encode()).hexdigest() |
There was a problem hiding this comment.
Hash algorithm mismatch between password hashing and verification
High Severity
hash_password_weak now produces SHA-256 hashes, but verify_password on line 40 still computes an MD5 hash for comparison. Any password hashed with hash_password_weak will never match when checked by verify_password, since the two algorithms produce different digests. The verification function needs to use the same hashlib.sha256 algorithm.


Summary
Fixes CodeQL alert #16: Use of a broken or weak cryptographic hashing algorithm on sensitive data
vulnerable_weak_crypto.pyFix Applied
See the diff for the specific secure coding change applied.
Fixes #18
Note
Medium Risk
Changes password hashing output in
hash_password_weak, which can break compatibility with previously stored hashes and impact authentication flows. The change is localized but touches security-sensitive behavior.Overview
Updates
hash_password_weakinvulnerable_weak_crypto.pyto usesha256instead ofmd5when hashing passwords, addressing the reported weak-hash CodeQL finding.Written by Cursor Bugbot for commit 287c45e. This will update automatically on new commits. Configure here.