Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-47065

CVE-2026-47065: Java Deserialization Auth Bypass Vulnerability

CVE-2026-47065 is an authentication bypass flaw in Java deserialization involving proxy class resolution and static initializer exploitation. This post covers the technical details, affected systems, and mitigation strategies.

Published:

CVE-2026-47065 Overview

CVE-2026-47065 covers two Java deserialization weaknesses tracked as ZDRES-232 and ZDRES-233. Both defects allow attackers to bypass deserialization allow-list controls intended to prevent gadget chain exploitation [CWE-502]. ZDRES-232 stems from a missing override of resolveProxyClass(), letting a crafted TC_PROXYCLASSDESC marker load arbitrary interfaces through java.lang.reflect.Proxy. ZDRES-233 abuses Class.forName(name, initialize=true, classLoader) in readClassDescriptor, which triggers the static initialiser of any allow-listed class before any instance is constructed. The vendor confirms both issues are fully addressed.

Critical Impact

Attackers who control a serialised stream can bypass deserialization accept-list filters and trigger arbitrary class loading or static initialiser side effects, leading to remote code execution.

Affected Products

  • Java applications relying on ObjectInputStream accept-list filters (acceptMatchers) for deserialization safety
  • Components dispatching to the default ObjectInputStream.resolveProxyClass(interfaces) implementation
  • Allow-list configurations using broad wildcard patterns such as accept("com.myapp.*")

Discovery Timeline

  • 2026-06-03 - CVE-2026-47065 published to the National Vulnerability Database (NVD)
  • 2026-06-03 - Last updated in NVD database

Technical Details for CVE-2026-47065

Vulnerability Analysis

The issue affects deserialization hardening logic that restricts which classes an ObjectInputStream will resolve. ZDRES-232 occurs when the serialised stream contains a TC_PROXYCLASSDESC marker. The JDK dispatches ObjectInputStream.readProxyDesc(), then calls the default resolveProxyClass(interfaces) implementation. That default invokes Class.forName(intf, false, latestUserDefinedLoader()) for each interface name and constructs the proxy class, never consulting the configured accept-list. An attacker who supplies a proxy descriptor referencing arbitrary interfaces escapes the filter entirely.

ZDRES-233 affects classes that are legitimately on the allow-list. During readClassDescriptor, the implementation calls Class.forName(name, initialize=true, classLoader). The initialize=true flag forces execution of the class’s <clinit> static initialiser before any object instance is created. Many real-world classes perform side-effecting work in static initialisers, including resource loading, network calls, and configuration mutation. An attacker supplies a class name that matches a wildcard such as accept("com.myapp.*") and gains code execution through the static initialiser.

Root Cause

The deserialization filter implementation did not override resolveProxyClass() and used eager class initialisation in readClassDescriptor. Both gaps allow control flow to reach class loading and static initialisation paths that the accept-list was supposed to gate [CWE-502].

Attack Vector

Exploitation requires the attacker to deliver an attacker-controlled byte stream to a deserialization endpoint. The proxy variant embeds a TC_PROXYCLASSDESC marker with arbitrary interface names. The static-initialiser variant supplies a class name that satisfies an existing allow-list wildcard. See the Apache Mailing List Discussion for protocol-level details.

The vulnerability mechanism is documented in prose because no verified public proof-of-concept code is referenced in the advisory.

Detection Methods for CVE-2026-47065

Indicators of Compromise

  • Serialised Java streams containing the TC_PROXYCLASSDESC (0x7D) marker arriving at endpoints that should only accept concrete classes
  • Unexpected Class.forName invocations resolving interfaces or classes outside the documented accept-list
  • Static initialiser activity (network connections, file writes, child processes) originating from classes matched by broad accept-list wildcards immediately after a deserialization call

Detection Strategies

  • Instrument ObjectInputStream subclasses to log every class and interface name resolved during deserialization, then compare against the configured accept-list.
  • Apply JVM-level deserialization filters (jdk.serialFilter) with explicit class lists rather than wildcard patterns, and alert on filter rejections.
  • Monitor application logs for readProxyDesc activity on services that do not legitimately exchange Java proxies.

Monitoring Recommendations

  • Forward JVM serialization filter logs and application stack traces to a centralised analytics platform for correlation.
  • Track outbound network connections from JVM processes immediately following inbound deserialization traffic.
  • Baseline static initialiser execution for allow-listed classes and alert on first-seen initialisation events in production.

How to Mitigate CVE-2026-47065

Immediate Actions Required

  • Upgrade the affected deserialization library to the fixed release referenced in the Apache Mailing List Discussion.
  • Replace wildcard accept patterns such as com.myapp.* with explicit class names that have been audited for safe static initialisers.
  • Disable Java serialization on network-facing endpoints where it is not strictly required.

Patch Information

The vendor states that ZDRES-232 and ZDRES-233 are fully addressed. The fix overrides resolveProxyClass() so proxy descriptors are filtered against the accept-list, and changes readClassDescriptor to resolve classes without forcing static initialisation. Apply the fixed library version to all consumers and rebuild downstream artifacts.

Workarounds

  • Configure a strict jdk.serialFilter global filter that rejects java.lang.reflect.Proxy and unknown class names before the vulnerable code path is reached.
  • Wrap ObjectInputStream usage in a subclass that overrides resolveProxyClass() to enforce the same accept-list applied to concrete classes.
  • Route deserialization traffic through a sanitising proxy that strips TC_PROXYCLASSDESC markers when proxies are not expected.
bash
# Configuration example: restrict JVM-wide deserialization with an explicit allow-list
java -Djdk.serialFilter='com.myapp.SafeDto;com.myapp.AnotherSafeDto;!*' \
     -Djdk.serialFilterFactory=com.myapp.security.StrictFilterFactory \
     -jar application.jar

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.