Skip to content

[Security] Fix CodeQL alert #16: Use of a broken or weak cryptographic hashing algorithm on sensitive data#90

Open
colin-d-fried wants to merge 1 commit into
mainfrom
security/codeql-16-weak-hash-password-fix
Open

[Security] Fix CodeQL alert #16: Use of a broken or weak cryptographic hashing algorithm on sensitive data#90
colin-d-fried wants to merge 1 commit into
mainfrom
security/codeql-16-weak-hash-password-fix

Conversation

@colin-d-fried
Copy link
Copy Markdown
Owner

@colin-d-fried colin-d-fried commented Mar 26, 2026

Summary

Fixes CodeQL alert #16: Use of a broken or weak cryptographic hashing algorithm on sensitive data

Field Value
Severity high
File vulnerable_weak_crypto.py
CWE CWE-327
Alert CodeQL Alert #16

Fix Applied

See the diff for the specific secure coding change applied.

Fixes #18


Open with Devin

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_weak in vulnerable_weak_crypto.py to use sha256 instead of md5 when 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.

Comment thread vulnerable_weak_crypto.py

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

Sensitive data (password)
is used in a hashing algorithm (SHA256) that is insecure for password hashing, since it is not a computationally expensive hash function.

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 os and base64 at the top of vulnerable_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_weak to:
    • 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.b64encode and join them with a separator (e.g., "salt$hash") into a single string for storage/verification.
  • 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.

Suggested changeset 1
vulnerable_weak_crypto.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/vulnerable_weak_crypto.py b/vulnerable_weak_crypto.py
--- a/vulnerable_weak_crypto.py
+++ b/vulnerable_weak_crypto.py
@@ -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()
EOF
@@ -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()
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment thread vulnerable_weak_crypto.py
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread vulnerable_weak_crypto.py

def hash_password_weak(password):
return hashlib.md5(password.encode()).hexdigest()
return hashlib.sha256(password.encode()).hexdigest()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CodeQL #16] Use of a broken or weak cryptographic hashing algorithm on sensitive data

2 participants