VNX-325: Missing Cryptographic Step
Reports AES in an unauthenticated mode (CBC, CTR, CFB, OFB) in Java, Kotlin, Node.js, PHP, Python and Ruby, in a file that never computes a MAC or signature, so the integrity step is missing. AEAD modes, ECB (VNX-CRYPTO-003) and files with an HMAC are not reported.
| Field | Value |
|---|---|
| Rule ID | VNX-325 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java, Kotlin, JavaScript / TypeScript, PHP, Python, Ruby |
| CWE | CWE-325 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | missing-crypto-step cwe-325 crypto unauthenticated-encryption |
| Source | internal/sast/rules/vnx-325.rego |
Overview
VNX-325 maps to CWE-325: Missing Cryptographic Step. It reports AES set up in a mode that provides confidentiality only (CBC, CTR, CFB, OFB, PCBC) when the same file never computes a MAC, an AEAD tag or a signature.
Why This Matters
Encryption without authentication lets an attacker flip bits in the ciphertext and have the change decrypt silently. CBC decryption without a MAC is also a padding oracle: an error that distinguishes bad padding is enough to decrypt the whole message.
What Gets Flagged
// FLAGGED: no Mac anywhere in the file
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
# FLAGGED
cipher = AES.new(key, AES.MODE_CBC, iv)
enc = Cipher(algorithms.AES(key), modes.CTR(iv)).encryptor()
// FLAGGED
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
$ct = openssl_encrypt($plain, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); // no hash_hmac in the file
cipher = OpenSSL::Cipher.new("aes-256-cbc")
What Is Not Flagged
- AEAD modes: GCM, CCM, EAX, SIV, OCB, ChaCha20-Poly1305.
- A file that also computes an HMAC, CMAC, Poly1305 tag or signature (
Mac.getInstance,hmac.new,createHmac,Signature). - ECB and bare
"AES", which VNX-CRYPTO-003 reports. - Comments, Python string literals and test files.
A MAC computed in a different file is not seen, so check a finding against its caller.
Remediation
- Prefer an AEAD: AES-GCM or ChaCha20-Poly1305.
- Otherwise encrypt-then-MAC: HMAC-SHA256 over the IV and ciphertext with a separate key, verified in constant time before decrypting.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-325
// nosec vnx-325
Or record an ignore rule: vulnetix ignore add --rule vnx-325 --reason "...". See Suppressing findings.