CVE-2026-47065: Java Deserialization Filter Bypass via resolveProxyClass
A critical Java deserialization vulnerability tracked as CVE-2026-47065 enables attackers to bypass serialization filters implemented via ObjectInputFilter by exploiting the TC_PROXYCLASSDESC (proxy class descriptor) token in a crafted serialized stream. With a CVSS v3.1 score of 9.8 (Critical), the flaw undermines defenses built on acceptMatchers filter chains — a commonly deployed mitigation against Java deserialization attacks — and can lead to unauthenticated remote code execution in affected Java applications.
The vulnerability was published to the NIST NVD on June 3, 2026.
Vulnerability Overview
| Attribute | Value |
|---|---|
| CVE ID | CVE-2026-47065 |
| CVSS Score | 9.8 (Critical) |
| CWE Classification | CWE-502 — Deserialization of Untrusted Data |
| Affected Component | Java ObjectInputStream — resolveProxyClass (JDK serialization) |
| Attack Vector | Network |
| Authentication Required | None |
| Primary Impact | Remote Code Execution (RCE) via serialization filter bypass |
| Source | NVD / NIST |
Technical Details
Background: Java Deserialization and ObjectInputFilter
Java's built-in serialization mechanism allows objects to be converted to byte streams (serialized) and reconstructed (deserialized). Deserialization of untrusted data has long been a critical attack vector because the deserialization process can trigger arbitrary code execution via gadget chains — sequences of object method calls that culminate in OS command execution.
To defend against this, Java introduced ObjectInputFilter (JEP 290, Java 9+), which allows applications to define allow/deny lists (acceptMatchers) specifying which classes are permitted to be deserialized. Many enterprise frameworks and security-hardened deployments rely on ObjectInputFilter as the primary defense against deserialization attacks.
The Vulnerability: resolveProxyClass Not Overridden
When a serialized stream contains a TC_PROXYCLASSDESC token (the marker for a java.lang.reflect.Proxy), the JDK's ObjectInputStream.readProxyDesc() method is dispatched to handle the proxy class descriptor. The critical issue is:
resolveProxyClass() is not subject to the same ObjectInputFilter acceptMatchers filter checks as regular class descriptors.
An attacker can craft a serialized payload that:
- Embeds a
TC_PROXYCLASSDESCinstead of aTC_CLASSDESC(regular class descriptor) - Specifies a
java.lang.reflect.Proxyimplementing interfaces that chain to a dangerousInvocationHandler - Bypasses
ObjectInputFilterentirely because the filter'sacceptMatcherslogic does not interceptresolveProxyClass()dispatch
This allows a fully crafted proxy-based gadget chain to execute arbitrary code even when a security filter is configured to block known dangerous classes.
Exploitation Path
Attacker sends crafted serialized payload over network
→ Payload uses TC_PROXYCLASSDESC instead of TC_CLASSDESC
→ ObjectInputStream.readProxyDesc() dispatched
→ resolveProxyClass() called — bypasses ObjectInputFilter acceptMatchers
→ java.lang.reflect.Proxy instantiated with malicious InvocationHandler
→ Gadget chain triggered during proxy method invocation
→ Arbitrary OS command execution (RCE)
Example Malicious Payload Structure (conceptual)
Serialized stream:
0xACED 0x0005 // Java serialization magic + version
TC_PROXYCLASSDESC // Triggers readProxyDesc() instead of readClassDesc()
interfaceCount = 1
interface[0] = "java.lang.Runnable" // Or another callable interface
TC_CLASSDESC // InvocationHandler with embedded gadget chain
className = "sun.reflect.annotation.AnnotationInvocationHandler"
... // Classic RCE gadget chain
The CVSS score of 9.8 reflects:
- Attack Vector: Network — remotely exploitable via any Java serialization endpoint
- Attack Complexity: Low — no special conditions or configuration required
- Authentication: None — unauthenticated exploitation
- All three impact dimensions: High (Confidentiality, Integrity, Availability)
Impact Assessment
| Impact Area | Description |
|---|---|
| Remote Code Execution | Full RCE on the JVM host via proxy-based gadget chain bypass |
| Filter Defense Nullified | Applications relying solely on ObjectInputFilter acceptMatchers are fully exposed |
| Broad Ecosystem Impact | Any Java application accepting serialized input from untrusted sources is potentially affected |
| Enterprise Middleware | Application servers (JBoss, WebLogic, WebSphere, JMX endpoints) historically vulnerable |
| Microservices | Services using Java serialization for RPC or messaging are exposed |
| CI/CD and DevOps | Build tools using Java deserialization for plugin loading may be affected |
This vulnerability is particularly significant because ObjectInputFilter adoption grew as the recommended mitigation for Java deserialization CVEs in 2017-2023 (CVE-2015-4852, CVE-2016-3510, etc.). Applications that implemented this control and considered themselves protected are now exposed.
Affected Systems
The vulnerability affects Java applications that:
- Accept serialized
ObjectInputStreaminput from untrusted sources - Rely on
ObjectInputFilter(JEP 290) as the primary deserialization defense - Do not override
resolveProxyClass()in theirObjectInputStreamsubclass
| Environment | Risk |
|---|---|
| Java EE / Jakarta EE application servers | High |
| JMX (Java Management Extensions) endpoints | High |
| RMI (Remote Method Invocation) services | High |
| Custom serialization-based messaging | High |
| Apache Commons Collections / BeanUtils users | High |
| Spring Framework with default serialization | Moderate (context-dependent) |
Check vendor advisories for your application server and framework for specific version-level guidance.
Remediation
Immediate Actions
-
Override
resolveProxyClass()in ObjectInputStream subclasses — Apply the filter check explicitly to proxy class descriptors:ObjectInputStream ois = new ObjectInputStream(inputStream) { @Override protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { // Apply the same allowlist logic as your ObjectInputFilter for (String iface : interfaces) { if (!isAllowed(iface)) { throw new InvalidClassException( "Proxy interface not allowed: " + iface); } } return super.resolveProxyClass(interfaces); } }; -
Update to patched JDK/JRE versions — Monitor Oracle and OpenJDK security advisories for releases that address CVE-2026-47065 and apply updates as soon as available:
java -version # Check current version # Apply vendor-specific update mechanism -
Adopt serialization-safe alternatives — Where feasible, replace Java native serialization with safer formats:
- JSON (Jackson, Gson, Moshi) with strict schema validation
- Protocol Buffers (protobuf) or FlatBuffers
- Apache Avro or Apache Thrift
-
Deploy Java agent-based protection — Tools like the Serial Killer agent or Contrast Security can intercept deserialization at the JVM level and block dangerous gadget chains regardless of filter bypasses.
-
Restrict serialization endpoints — If Java serialization endpoints (RMI, JMX, IIOP) are not required externally, firewall them off:
# Block RMI default port range from external access iptables -A INPUT -p tcp --dport 1099 -s <internal-management-cidr> -j ACCEPT iptables -A INPUT -p tcp --dport 1099 -j DROP
Defense-in-Depth
Priority 1: Override resolveProxyClass() to apply filter logic to proxy descriptors
Priority 2: Update JDK to patched version once available
Priority 3: Deploy JVM-level deserialization agent (Serial Killer, Contrast, etc.)
Priority 4: Replace Java serialization with JSON/protobuf where feasible
Priority 5: Network-level firewall on all serialization-facing ports (RMI, JMX)
Priority 6: Runtime monitoring for unexpected class loading during deserialization
Historical Context
Java deserialization vulnerabilities have been a recurring critical-severity threat class since the "Marshalling Pickles" research (2015):
| Year | Notable CVE | Description |
|---|---|---|
| 2015 | CVE-2015-4852 | Oracle WebLogic RCE via deserialization |
| 2016 | CVE-2016-3510 | JBoss/WildFly deserialization RCE |
| 2017 | CVE-2017-3248 | WebLogic T3 deserialization bypass |
| 2020 | CVE-2020-14750 | WebLogic RCE — JEP 290 filter bypass |
| 2026 | CVE-2026-47065 | resolveProxyClass filter bypass — nullifies acceptMatchers |
CVE-2026-47065 represents the latest evolution in this chain: as defenders adopted ObjectInputFilter as the standard mitigation, attackers identified the resolveProxyClass gap that the filter mechanism does not cover by default.
Key Takeaways
- CVE-2026-47065 is a CVSS 9.8 critical Java deserialization filter bypass exploiting the
resolveProxyClass()path not covered byObjectInputFilteracceptMatchers - Applications that implemented
ObjectInputFilteras their sole deserialization defense are fully exposed — the bypass renders that control ineffective without additional steps - The fix requires explicitly overriding
resolveProxyClass()to apply the same allowlist logic used by the main filter - Long-term mitigation requires migrating away from Java native serialization to safer data exchange formats
- All Java applications accepting serialized input from untrusted sources should be treated as vulnerable until assessed