DL4J Deserialization PoC (CWE-502)
Security Research Only - This repository contains a proof-of-concept demonstrating CWE-502 (Deserialization of Untrusted Data) in DL4J ModelSerializer.
Vulnerability
ModelSerializer.restoreMultiLayerNetwork() uses raw ObjectInputStream.readObject() to deserialize the preprocessor.bin entry from model ZIP files without any ObjectInputFilter, resolveClass() override, or class allowlist.
Vulnerable Code (ModelSerializer.java, lines 390-396)
byte[] prep = zipFile.get(PREPROCESSOR_BIN);
if (prep != null) {
InputStream stream = new ByteArrayInputStream(prep);
ObjectInputStream ois = new ObjectInputStream(stream);
preProcessor = (DataSetPreProcessor) ois.readObject(); // Arbitrary deserialization
}
Additional Vulnerable Paths
restoreComputationGraphHelper()(lines 615-627) - same patterngetObjectFromFile()(line 876) - deserializes arbitrary objects fromobjects/<key>entriesrestoreNormalizerFromInputStreamDeprecated()(line 971) - deprecated fallback
Files
malicious_model.zip- DL4J model ZIP containing URLDNS gadget chain inpreprocessor.binDL4JExploit.java- PoC generator source code
Reproduction
import org.deeplearning4j.util.ModelSerializer;
// Loading this model triggers ObjectInputStream.readObject() on the
// attacker-controlled preprocessor.bin payload
ModelSerializer.restoreMultiLayerNetwork(new File("malicious_model.zip"));
// DNS lookup to attacker domain confirms arbitrary deserialization
Impact
CVSS 7.8 (High) - An attacker can achieve arbitrary code execution by distributing a malicious DL4J model file. The exploit triggers during standard model loading with no special API calls required.
Fix
Use ObjectInputFilter (Java 9+) to restrict deserializable classes, or migrate to a safer serialization format (e.g., JSON via Jackson).
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support