VNX-1240: Use of a Cryptographic Primitive with a Risky Implementation
A Java javax.crypto.Cipher is created for a block cipher in ECB mode, which encrypts equal plaintext blocks to equal ciphertext blocks and so leaks the structure of the data and allows blocks to be cut, replayed and reordered. Reported: Cipher.getInstance() whose transformation names ECB for a block cipher ("AES/ECB/PKCS5Padding", "DESede/ECB/NoPadding", any case, with or without a provider argument), a bare block-cipher name ("AES", "DES", "DESede", "Blowfish", "RC2" and the like) for which the JCE provider default is ECB, the transformation written on the line after the opening parenthesis, and a Cipher.getInstance(NAME) whose NAME is a constant assigned such a transformation in the same file. Not reported: GCM, CCM, CBC, CTR and other modes, ChaCha20, AESWrap, RSA/ECB/... (RSA has no chaining; padding is judged by VNX-780), KeyGenerator.getInstance("AES") and SecretKeySpec(..., "AES"), a transformation passed in a variable whose value is not visible in the file, the text in comments or inside other string literals, and every call VNX-CRYPTO-003 (AES in ECB mode, CWE-327) reports: an explicit /ECB/ transformation, a bare block-cipher name, a constant or a getProperty default holding one, and a call split after getInstance( (reported there on the call line). Those are reported by VNX-CRYPTO-003, so a Java ECB cipher is one finding rather than two. What that rule does not report stays here: a mode concatenated onto the algorithm (alg + "/ECB/PKCS5Padding"), a getOrDefault default, and ECB in test sources, which VNX-CRYPTO-003 leaves out.
| Field | Value |
|---|---|
| Rule ID | VNX-1240 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java |
| CWE | CWE-1240 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | risky-primitive ecb java cwe-1240 |
| Source | internal/sast/rules/vnx-1240.rego |
Overview
VNX-1240 maps to CWE-1240: Use of a Cryptographic Primitive with a Risky Implementation.
Why This Matters
ECB encrypts each block independently, so equal plaintext blocks give equal ciphertext blocks. The structure of the data shows through the encryption, and an attacker can cut, replay and reorder blocks without knowing the key. In Java, asking for a bare algorithm name such as "AES" selects ECB through the provider default, so the mode is often chosen by accident.
What Gets Flagged
Most ECB in Java is reported by VNX-CRYPTO-003 (AES in ECB mode, CWE-327): an explicit /ECB/ transformation, a bare block-cipher name such as "AES" whose provider default is ECB, a constant or a getProperty default holding one, and a call split after getInstance(. This rule does not report those calls again, so a Java ECB cipher is one finding. It reports the forms VNX-CRYPTO-003 does not:
Cipher cipher = Cipher.getInstance(alg + "/ECB/PKCS5Padding"); // mode concatenated on
String t = conf.getOrDefault("vault.cipher", "AES/ECB/PKCS5Padding");
Cipher c = Cipher.getInstance(t); // getOrDefault default
// src/test/java/...: ECB in test sources, which VNX-CRYPTO-003 leaves out
Cipher fixture = Cipher.getInstance("AES/ECB/PKCS5Padding");
Not flagged: "AES/GCM/NoPadding", "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" (RSA has no chaining), KeyGenerator.getInstance("AES"), new SecretKeySpec(raw, "AES"), and Cipher.getInstance("AES/ECB/PKCS5Padding") in production code, which VNX-CRYPTO-003 reports.
Remediation
- Use an authenticated mode:
Cipher.getInstance("AES/GCM/NoPadding")with a fresh 12-byte IV for every encryption. - Always spell out the full transformation; never rely on the provider default.
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-1240
// nosec vnx-1240
Or record an ignore rule: vulnetix ignore add --rule vnx-1240 --reason "...". See Suppressing findings.