skills/length-extension-attacks-anti-pattern/SKILL.md
Security anti-pattern for hash length extension vulnerabilities (CWE-328). Use when generating or reviewing code that uses hash(secret + message) for authentication, API signatures, or integrity verification. Detects Merkle-Damgard hash misuse.
npx skillsauth add igbuend/grimbard length-extension-attacks-anti-patternInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Severity: High
Hash length extension attacks exploit Merkle-Damgård construction vulnerabilities in MD5, SHA-1, and SHA-256. Attackers knowing hash(secret + message) and secret length can compute hash(secret + message + padding + attacker_data) without knowing the secret. This enables appending data to signed messages with valid signatures, completely breaking message integrity and authentication.
Never use vulnerable hash functions (MD5, SHA-1, SHA-256) in hash(secret + message) construction for MACs. Use HMAC instead.
# VULNERABLE: Using hash(secret + message) for message signature
import hashlib
SECRET_KEY = b"my_super_secret_key_16b" # 16 bytes
def get_signed_url(message):
# Signature created by prepending secret to message and hashing
# Vulnerable to length extension
signature = hashlib.sha256(SECRET_KEY + message.encode()).hexdigest()
return f"/api/action?{message}&signature={signature}"
def verify_request(message, signature):
expected_signature = hashlib.sha256(SECRET_KEY + message.encode()).hexdigest()
return signature == expected_signature
# 1. Legitimate URL generated:
# Message: "user=alice&action=view"
# URL: /api/action?user=alice&action=view&signature=...
# 2. Attacker intercepts URL. Knows signature and message.
# Doesn't know SECRET_KEY but can guess length (16 bytes)
# 3. Using `hashpump`, attacker computes new valid signature for extended message
# Original: "user=alice&action=view"
# Extended: "user=alice&action=view" + padding + "&action=delete&target=bob"
# Tool generates new signature and message with padding
# 4. Server receives forged request, recomputes hash of `SECRET_KEY + extended_message`,
# finds it matches attacker's signature. Delete action processed
# SECURE: Use HMAC (Hash-based Message Authentication Code)
import hmac
import hashlib
SECRET_KEY = b"my_super_secret_key_16b"
def get_signed_url_secure(message):
# HMAC designed to prevent length extension attacks
# Two-step hashing: hash(key XOR opad, hash(key XOR ipad, message))
signature = hmac.new(SECRET_KEY, message.encode(), hashlib.sha256).hexdigest()
return f"/api/action?{message}&signature={signature}"
def verify_request_secure(message, signature):
expected_signature = hmac.new(SECRET_KEY, message.encode(), hashlib.sha256).hexdigest()
# Use hmac.compare_digest for constant-time comparison, prevents timing attacks
return hmac.compare_digest(signature, expected_signature)
# Attacker cannot extend HMAC-signed message without secret key
# Inner hash `hash(key XOR ipad, message)` prevents continuing hash chain
JavaScript/Node.js:
// VULNERABLE: hash(secret + message) construction
const crypto = require('crypto');
const SECRET = 'my_secret_key';
function signMessage(message) {
// Vulnerable to length extension!
const signature = crypto.createHash('sha256')
.update(SECRET + message)
.digest('hex');
return signature;
}
// SECURE: Use HMAC
const crypto = require('crypto');
const SECRET = 'my_secret_key';
function signMessageSecure(message) {
const signature = crypto.createHmac('sha256', SECRET)
.update(message)
.digest('hex');
return signature;
}
// Verify with constant-time comparison
function verifySignature(message, signature) {
const expected = signMessageSecure(message);
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Java:
// VULNERABLE: Manual hash(secret + message)
import java.security.MessageDigest;
public class InsecureSigning {
private static final String SECRET = "my_secret_key";
public static String signMessage(String message) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// Vulnerable to length extension!
String combined = SECRET + message;
byte[] hash = digest.digest(combined.getBytes());
return bytesToHex(hash);
}
}
// SECURE: Use HMAC
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
public class SecureSigning {
private static final String SECRET = "my_secret_key";
public static String signMessage(String message) throws Exception {
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(
SECRET.getBytes(), "HmacSHA256");
hmac.init(secretKey);
byte[] hash = hmac.doFinal(message.getBytes());
return bytesToHex(hash);
}
// Constant-time comparison
public static boolean verifySignature(String message, String signature)
throws Exception {
String expected = signMessage(message);
return MessageDigest.isEqual(
signature.getBytes(),
expected.getBytes()
);
}
}
rg 'hashlib\.(md5|sha1|sha256)\(.*\+' --type pyrg 'crypto\.createHash.*update.*\+' --type jsrg 'MessageDigest.*update.*\+' --type javahash(key + data) or hash(data + key) patternsrg 'hashlib\.(md5|sha1|sha256)' --type py | rg -v 'hmac'rg 'crypto\.createHash\(' --type js | rg -v 'createHmac'rg 'MessageDigest\.getInstance.*MD5|SHA-1|SHA-256' --type java | rg -v 'Mac\.getInstance'rg 'signature.*=.*hash|mac.*=.*hash' -ipython.lang.security.audit.hashlib-weak-hashB303 (MD5/SHA1 usage)hash(message + secret) or hash(secret + message + secret). Use HMACdevelopment
Security anti-pattern for Cross-Site Scripting vulnerabilities (CWE-79). Use when generating or reviewing code that renders HTML, handles user input in web pages, uses innerHTML/document.write, or builds dynamic web content. Covers Reflected, Stored, and DOM-based XSS. AI code has 86% XSS failure rate.
development
Security anti-pattern for XPath injection vulnerabilities (CWE-643). Use when generating or reviewing code that queries XML documents, constructs XPath expressions, or handles user input in XML operations. Detects unescaped quotes and special characters in XPath queries.
development
Security anti-pattern for weak password hashing (CWE-327, CWE-759). Use when generating or reviewing code that stores or verifies user passwords. Detects use of MD5, SHA1, SHA256 without salt, or missing password hashing entirely. Recommends bcrypt, Argon2, or scrypt.
development
Security anti-pattern for weak encryption (CWE-326, CWE-327). Use when generating or reviewing code that encrypts data, handles encryption keys, or uses cryptographic modes. Detects DES, ECB mode, static IVs, and custom crypto implementations.