[java] InsecureCryptoIv: False negative when a hard-coded IV is constructed through default array initialization
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 5.5k
- Forks
- 1.6k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 54
Description
Affects PMD Version: 7.26.0
Rule:
InsecureCryptoIv
https://docs.pmd-code.org/latest/pmd_rules_java_security.html#insecurecryptoiv
Description:
InsecureCryptoIv can detect cases where the IV contents are explicitly specified using an array initializer, for example:
byte[] iv = new byte[] {
0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f
};
IvParameterSpec ivSpec = new IvParameterSpec(iv);
However, for the case where a fixed-length array is allocated without an explicit array initializer, the rule does not report a violation:
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv);
In Java, newly created arrays of primitive types are automatically initialized with their default values. For byte[], the default value of each element is 0. Therefore, in byte[] iv = new byte[16];, all 16 elements of iv are deterministically set to 0, and the value ultimately passed to IvParameterSpec is also completely determined by the source code:
{0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0}
Although these 0 values do not appear explicitly as literals in the source code, the actual contents of the array are determined by Java's default initialization semantics. Therefore, from the perspective of the rule, this case could also be worth considering for detection. The following test case demonstrates this behavior. The first case is reported by InsecureCryptoIv, whereas the second case does not produce a warning. Therefore, this case could be considered a potential false negative.
Code Sample demonstrating the issue:
// Explicitly initialized IV
package com.example;
import javax.crypto.spec.IvParameterSpec;
public class BadCase {
public static void main(String[] args) {
// Hardcoded IV using a fixed byte array
byte[] iv = new byte[] {
0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f
}; // [REPORTED LINE]
IvParameterSpec ivSpec = new IvParameterSpec(iv);
}
}
// Default array initialization
package com.example;
import javax.crypto.spec.IvParameterSpec;
public class BadCase_Var {
public static void main(String[] args) {
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv);// [should be flagged]
}
}
Expected outcome:
InsecureCryptoIv could consider locally allocated primitive arrays with statically known default values when determining whether an IV is a fixed, hard-coded value. For example:
byte[] iv = new byte[16];
IvParameterSpec ivSpec = new IvParameterSpec(iv);
could be considered by the rule because the contents of iv are deterministically known to be all zeroes. A possible improvement would be to extend the handling of ASTArrayAllocation to account for Java's default array initialization semantics. In particular, the checker could:
- Determine whether the allocated array has a statically known length;
- Determine whether its element type has a deterministic default value;
- Treat an array without an explicit initializer as having those default values;
- Propagate the resulting array contents to subsequent uses;
- Evaluate whether the resulting IV is a fixed value that should be reported by InsecureCryptoIv.
This would allow the rule to consider fixed IVs even when their constant contents arise implicitly from Java's array initialization semantics rather than from an explicit ASTArrayInitializer.
This is a false-negative case.
Running PMD through: CLI
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the InsecureCryptoIv rule and its handling of ASTArrayAllocation, then reproduce the issue through the CLI using the default-initialized byte array shown in the report. Trace how array contents are propagated to IvParameterSpec. Done means the default-initialized fixed-length array is reported consistently with the explicit initializer case, with regression coverage added where the rule tests are located.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100