“This building is protected by a very secure system … But like all systems it has a weakness. The system is based on the rules of a building. One system built on another.” (Keymaker – “The Matrix Reloaded”)
Summary
Six issues related to how Java handles JAR files, ZIP files and digital signatures in JAR files were reported to and fixed by OpenJDK / Oracle. These could be used to hide malicious files inside JARs, bypass digital signatures and overwrite existing content. One of the issues was assigned as CVE (CVE-2024-20932) and the rest were fixed without CVE assignments.
Technical Details
The Java programming language supports the use of digital signatures to validate the authenticity of Java class files packaged into JAR files (JAR = Java ARchive). These are based on the ZIP file format with additional of a special digital signature schema which uses a set of special manifest files included in the ZIP file itself containing digital signatures applying to the rest of the files in the archive (unlike other signature schemes such as PGP or sigstore). This can lead to security issues related to how the manifest files or other files in the archive are stored or processed.
Java also includes a number of classes and CLI utilities dealing with JAR files – all supporting digital signature validation:
JarFile – uses the central directory
JarInputStream – reads ZIP files in streaming mode, ignoring the central directory
jar (cli) – used to create, update and extract JARs
jarsigner (cli) – used to sign and verify digital signatures for JAR files
A key point to keep in mind regarding ZIP is that entries in the ZIP files appear through out the file (local) but also appear in an index located in the end of the file (central directory). Normal processing is done by reading the central directory then referencing entries from there but it is possible to process ZIP files in “streaming” mode by ignoring the central directory and reading the entries directly. This can introduce an number of security issues by exploiting the differences between the two approaches. A good overview of this, the ZIP format and various ZIP attacks can be found here: https://www.youtube.com/watch?v=8Uue8tARdNs.
Issue #1 – Duplicate File Handling in jar CLI
The Java jar cli did not correctly handle a case where two entries with the same file name would appear in the same JAR file. This could be exploited to hide a malicious file as a second duplicate entry and used to overwrite a legit file already in the JAR or bypass signature validation. This issue was fixed by adding detection for this edge case on May 28th, 2025 and the fix was shipped in the following JDK versions: 25. See release notes:
“The jar –validate command has been enhanced to identify and generate a warning message for: … Duplicate entry names”
The following Java code can be used for generate a proof of concept JAR:
You can test this on a fixed version of the JDK (25) by running the validate command:
Issue #2 – Overwriting existing files via jar CLI (-x)
The Java jar cli includes an extract (-x) option which extracts files to the file system. The tool didn’t check if the files being extracted are overwriting a file already present. This can be exploited to overwrite security sensitive files without user’s knowledge. The issue was fixed by adding a new option (–keep-old-files / -k) which will prevent overwriting of files. This was fixed on October 23th, 2024 and shipped in the following JDK versions: 21.0.6, 17.0.14, 11.0.27 and 8u452. The following was added to the release notes:
“The jar tool’s extract operation has been enhanced to allow the –keep-old-files and the -k options to be used in preventing the overwriting of existing files. … Either of these commands will extract the contents of foo.jar. If an entry with the same name already exists in the target directory, then the existing file will not be overwritten.”
The following shell script can be used as proof of concept:
Issue #3 – Duplicate directory entries (JDK17 only) – CVE-2024-20932
The ZIP classes in Java failed to correctly handle an edge case where two entries exist in a ZIP file, one as a file and another that’s a directory. Can be exploited to bypass certain restrictions or hide malicious data. This was fixed on January 9th, 2024 and shipped in the following JDK versions: 17.0.19. CVE-2024-20932 was assigned to this issue:
“It was discovered that the Libraries component in OpenJDK failed to properly handle ZIP archives that contain a file and directory entry with the same name within the ZIP file. This could lead to integrity issues when extracting data from such archives. An untrusted Java application or applet could use this flaw to bypass Java sandbox restrictions.”
The following Java code is a proof of concept for this issue:
Issue #4 – Incorrect handling of duplicate manifest files (JarInputStream)
The JarInputStream incorrectly handled cases where the manifest would appear twice in the same JAR file in regards to digital signatures. This was fixed on April 16th, 2025 and shipped in the following JDK versions: 21.0.7, 17.0.15, 11.0.27 and 8u452. See release notes:
“The JarInputStream class now treats a signed JAR as unsigned if it detects a second manifest within the first two entries in the JAR file. A warning message “WARNING: Multiple MANIFEST.MF found. Treat JAR file as unsigned.” is logged if the system property, -Djava.security.debug=jar, is set.”
No POC code is available
Issue #5 – Digital signature bypass via local/central header confusion
The various CLIs and classes handling JAR files read file entries either as streaming (local headers) or central directory mode. It is possible for an attacker to exploit the differences between the various implementations by adding file entries to the local headers which will pass digital signature validation based on central directory and then be extract when local headers / streaming mode is used. This issue was fixed by adding detection for this edge case on May 28th, 2025 and the fix was shipped in the following JDK versions: 25.b26. See release notes:
“The jar –validate command has been enhanced to identify and generate a warning message for … Inconsistencies in the ordering of entries between the LOC and CEN headers”
No POC code is available
Issue #6 – No detection of signed content being removed (jarsigner)
The Java jarsigner cli failed to detect when a digitally signed JAR file had some file entries removed. This can be exploited to impact security by removing service provider classes or security policy files. The issue was fixed by adding detection of deleted content that was digitally signed and the fix was shipped in the following JDK versions: 21.0.8, 17.0.16, 11.0.28 and 8u462. This was fixed on October 2nd, 2024 – see release notes:
“If an entry is removed from a signed JAR file, there is no mechanism to detect that it has been removed using the JarFile API, since the getJarEntry method returns null as if the entry had never existed. With this change, the jarsigner -verify command analyzes the signature files and if some sections do not have matching file entries, it prints out the following warning: “This JAR contains signed entries for files that do not exist”. Users can further find out the names of these entries by adding the -verbose option to the command.”
The following shell script can be used as a proof of concept:
Disclosure Information and References
With exception of issue # 3 above (CVE-2024-20932), all remaining issues were not issued a CVE and some received an in-depth security fix acknowledgement by Oracle / OpenJDK.
Issue #1 – Duplicate File Handling in jar CLI:
Bug: https://bugs.openjdk.org/browse/JDK-8345431
Git commit: https://github.com/openjdk/jdk/commit/cd052c72cdb62186e66c1d2ecf9216f3df61b242
Fixed versions: 25
Issue #2 – Overwriting existing files via jar CLI (-x):
Bug: https://bugs.openjdk.org/browse/JDK-8335912
Git commit: https://github.com/openjdk/jdk/commit/158b93d19a518d2b9d3d185e2d4c4dbff9c82aab
Fixed versions: 21.0.6, 17.0.14, 11.0.27 and 8u452
Issue #3 – Duplicate directory entries (JDK17 only):
CVE: https://nvd.nist.gov/vuln/detail/cve-2024-20932
Git commit: https://github.com/openjdk/jdk17u/commit/f6f32bf256e34447f54be823fdfb2e64e235e404
Redhat Bugzilla entry: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2024-20932
Issue #4 – Incorrect handling of duplicate manifest files (JarInputStream):
Bug: JDK-8337494
Git commit: https://github.com/openjdk/jdk/commit/ef38a04b448f97036c516ba87cb86afcc7559d1f
Fixed versions: 21.0.7, 17.0.15, 11.0.27 and 8u452
Issue #5 – verification bypass via local/central header confusion:
Bug: https://bugs.openjdk.org/browse/JDK-8345431
Git commit: https://github.com/openjdk/jdk/commit/cd052c72cdb62186e66c1d2ecf9216f3df61b242
Fixed versions: 25
Issue #6 – No detection of signed content being removed (jarsigner):
Bug: https://bugs.openjdk.org/browse/JDK-8309841
Git commit: https://github.com/openjdk/jdk/commit/bdfb41f977258831e4b0ceaef5d016d095ab6e7f
Fixed versions: 25.b26
Acknowledgements
The author would like to thank everyone who was involved in the disclosure process for these issues – you know who you are.
No Responses