VNX-928: Broken or obsolete cipher (DES, 3DES, RC4, RC2, Blowfish) in Kotlin
CWE-928 is the OWASP Top Ten 2013 view; this rule reports its most concrete Kotlin manifestation, a broken or obsolete symmetric cipher (A6 Sensitive Data Exposure). Java is reported by VNX-CRYPTO-004 (Broken or obsolete cipher, CWE-327), which reads the same JCA and Bouncy Castle forms, so a weak cipher in a .java file is one finding rather than two; this rule reads .kt files only. Reported in Kotlin: Cipher, SecretKeyFactory or KeyGenerator .getInstance with DES, DESede/TripleDES/3DES, RC4/ARCFOUR, RC2 or Blowfish (any mode and padding, the argument possibly on the next line) or a password-based scheme built on one (PBEWithMD5AndDES, PBEWithSHA1AndDESede, PBEWithSHAAnd40BitRC4), Bouncy Castle new DESEngine/DESedeEngine/RC4Engine/RC2Engine/BlowfishEngine(), the same algorithm passed through a String constant assigned in the same file, new SecretKeySpec(key, "DES"/"RC4"/...), and new DESKeySpec/DESedeKeySpec. Not reported: AES, ChaCha20 and RSA transformations, algorithm names in comments, log messages or other string literals not passed to a crypto API, and identifiers that only start with DES (DESCRIPTOR, DESIGN). A constant defined in another file is not followed.
| Field | Value |
|---|---|
| Rule ID | VNX-928 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Kotlin |
| CWE | CWE-928 |
| 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 | weak-crypto-mobile crypto cwe-928 |
| Source | internal/sast/rules/vnx-928.rego |
Overview
CWE-928 is the OWASP Top Ten 2013 view; this rule reports its most concrete Kotlin manifestation, a broken or obsolete symmetric cipher (A6 Sensitive Data Exposure): Cipher, SecretKeyFactory or KeyGenerator .getInstance with DES, DESede/TripleDES/3DES, RC4/ARCFOUR, RC2 or Blowfish (any mode and padding), the same algorithm passed through a String constant assigned in the same file, new SecretKeySpec(key, “DES”/“RC4”/…), and new DESKeySpec/DESedeKeySpec. Not reported: AES, ChaCha20 and RSA transformations, algorithm names in comments, log messages or other string literals not passed to a crypto API, and identifiers that only start with DES (DESCRIPTOR, DESIGN). A constant defined in another file is not followed.
Java is reported by VNX-CRYPTO-004, which reads the same JCA and Bouncy Castle forms (and more of them: a getProperty default, CAST5 and IDEA) as CWE-327. A weak cipher in a .java file is therefore one finding, not one from each rule; this rule reads .kt files only, which VNX-CRYPTO-004 does not.
Why This Matters
DES has a 56-bit key that can be brute-forced, 3DES and Blowfish have 64-bit blocks open to Sweet32 collision attacks, and RC4 and RC2 are broken. Data encrypted with them should be treated as recoverable.
What Gets Flagged
val c = Cipher.getInstance("DES/CBC/PKCS5Padding")
val rc4 = Cipher.getInstance( "RC4" )
val spec = SecretKeySpec(raw, "RC4")
private const val TRANSFORMATION = "DESede/ECB/PKCS5Padding"
fun cipher(): Cipher = Cipher.getInstance(TRANSFORMATION)
What Is Not Flagged
val c = Cipher.getInstance("AES/GCM/NoPadding")
val x = Cipher.getInstance("ChaCha20-Poly1305")
log.info("DES is not supported")
// Java: reported by VNX-CRYPTO-004, not repeated here
Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
Remediation
- Use AES-GCM (
AES/GCM/NoPadding) with a 128- or 256-bit key and a unique 12-byte IV per message, or ChaCha20-Poly1305. - Re-encrypt stored data that was protected with a broken cipher.
- For a confirmed false positive, add a
vulnetix-ignore: VNX-928comment on the line.
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-928
// nosec vnx-928
Or record an ignore rule: vulnetix ignore add --rule vnx-928 --reason "...". See Suppressing findings.