Skip to content

GHSA-LOG4J2-4255-MARSHALLEDOBJECT: Verified Reproduction

GHSA-LOG4J2-4255-MARSHALLEDOBJECT: Apache Log4j2 serialized LogEvent filter bypass to conditional RCE

GHSA-LOG4J2-4255-MARSHALLEDOBJECT is verified against org.apache.logging.log4j:log4j-core · maven. Affected versions: log4j-api 2.11.0-2.26.1; log4j-core 2.8.0-2.26.1 (verified against official 2.26.1 jars from Maven Central). Fixed in none yet - upstream issue open, waiting-for-maintainer label; no CVE/GHSA assigned. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00338.

REPRO-2026-00338 org.apache.logging.log4j:log4j-core · maven RCE Aug 26, 2026 .txt
Severity
CRITICAL
Confidence
HIGH
Reproduced in
73m 31s
Tool calls
447
Spend
$14.11
01 · Overview

What Is GHSA-LOG4J2-4255-MARSHALLEDOBJECT?

GHSA-LOG4J2-4255-MARSHALLEDOBJECT is a critical-severity RCE vulnerability affecting org.apache.logging.log4j:log4j-core log4j-api 2.11.0-2.26.1; log4j-core 2.8.0-2.26.1 (verified against official 2.26.1 jars from Maven Central). Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00338).

02 · Severity & CVSS

GHSA-LOG4J2-4255-MARSHALLEDOBJECT Severity

GHSA-LOG4J2-4255-MARSHALLEDOBJECT is rated critical severity.

CRITICAL threat level
Weakness CWE-502 — Deserialization of Untrusted Data

Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.

03 · Affected Versions

Affected org.apache.logging.log4j:log4j-core Versions

org.apache.logging.log4j:log4j-core · maven versions log4j-api 2.11.0-2.26.1; log4j-core 2.8.0-2.26.1 (verified against official 2.26.1 jars from Maven Central) are affected.

How to Reproduce GHSA-LOG4J2-4255-MARSHALLEDOBJECT

$ pruva-verify REPRO-2026-00338
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00338/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for GHSA-LOG4J2-4255-MARSHALLEDOBJECT

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

One exact serialized Log4jLogEvent.LogEventProxy byte stream whose MarshalledObject contains a Commons Collections CC6 Runtime.exec graph, replayed over unauthenticated TCP to vulnerable and patched receivers (payload SHA-256 recorded in logs/payload_identity.txt).

Attack chain
  1. Apache logging-log4j-samples TcpSocketServer.SocketHandler accepts TCP
  2. ObjectInputStreamLogEventBridge.wrapStream
  3. FilteredObjectInputStream(socket.getInputStream()).readObject
  4. Log4jLogEvent.LogEventProxy.readResolve/message
  5. MarshalledObject.get
  6. inner ObjectInputStream
  7. CC6 Runtime.exec.
Runnable proof: reproduction_steps.sh
Captured evidence: receiver fixed a1receiver fixed a2
How the agent worked 832 events · 447 tool calls · 2h 0m
2h 0mDuration
447Tool calls
112Reasoning steps
832Events
14Dead-ends
Agent activity over 2h 0m
Policy
1
Support
8
Repro
694
Judge
123
0:00120:18

Root Cause and Exploit Chain for GHSA-LOG4J2-4255-MARSHALLEDOBJECT

Versions: components: log4j-api 2.11.0 through 2.26.1 and log4j-core 2.8.0 through 2.26.1 when used by a FOIS-based serialized-event receiver.
  • Validated product path: org.apache.logging.log4j.server.TcpSocketServer with ObjectInputStreamLogEventBridge from Apache logging-log4j-samples commit 672a1555c7f5670e7affcc7b9984a90b492eb322, running official Log4j API/Core 2.26.1 artifacts.
  • Risk: Critical where this unauthenticated serialized-event listener is reachable and a usable gadget library is on the receiver classpath. An attacker can bypass the intended class allowlist and execute commands with the receiver process account.

Impact Parity

  • Disclosed/claimed maximum impact: Remote unauthenticated arbitrary deserialization leading to code execution.
  • Reproduced impact from this run: Remote receiver-side command execution through the required TCP entrypoint. A single generated CC6 payload file was replayed unchanged to two vulnerable JVM instances and produced process-unique PWNED-TIER2 markers containing receiver-side shell and parent process IDs plus account identity.
  • Parity: full.
  • Not demonstrated: Privilege escalation beyond the account running the receiver was not claimed or tested.

Root Cause

Vulnerable log4j-api includes java.rmi.MarshalledObject in SerializationUtil.REQUIRED_JAVA_CLASSES. FOIS checks outer class descriptors in resolveClass(), but the object graph stored by MarshalledObject is opaque bytes at that stage. During deserialization of Log4jLogEvent.LogEventProxy, readResolve() calls message(), which calls marshalledMessage.get(). That operation deserializes the inner graph in another ObjectInputStream, outside FOIS's class-name check. A non-allowlisted object can therefore execute its readObject() callback, and a receiver-loadable gadget graph can reach Runtime.exec.

The tested minimal correction removes java.rmi.MarshalledObject from REQUIRED_JAVA_CLASSES, causing FOIS to reject the carrier before its inner bytes are unpacked. bundle/logs/fix.patch records the exact change. The upstream report is https://github.com/apache/logging-log4j2/issues/4255; it was still open at reproduction time and did not identify a merged fix commit, so the negative control applies the report's minimal suggested fix to official 2.26.1 source.

Reproduction Steps

  1. Run bash bundle/repro/reproduction_steps.sh from any directory. The script uses PRUVA_ROOT or resolves the bundle path itself.
  2. It reads bundle/project_cache_context.json, uses <project_cache_dir>/repo when prepared, verifies the Apache samples origin and exact commit, and extracts the real log4j-server sources.
  3. It verifies official Log4j 2.26.1 and Commons Collections 3.2.1 jar hashes, compiles the real TcpSocketServer and ObjectInputStreamLogEventBridge classes, and records their runtime CodeSource paths.
  4. It generates each serialized payload once and sends the exact file bytes over localhost TCP. It performs direct unwrapped-object rejection, wrapped inner deserialization twice, wrapped CC6 command execution twice, the same tier-2 bytes against two patched receivers, and the same bytes against -Djdk.serialFilter=!java.rmi.MarshalledObject.
  5. It validates all assertions and writes bundle/repro/runtime_manifest.json. Exit 0 means the claim is confirmed.

Evidence

  • Exact identity: bundle/logs/target_identity.txt binds samples commit 672a1555c7f5670e7affcc7b9984a90b492eb322, Log4j commit dd0f9d255e24e6bcc13bd2641407a409c0524803, official API/Core jar hashes, target digest 7310f18dd2601851bcc37b1963906cbd86f417a18b196251c8fe64a6b3b18673, and runtime digest 98b16715ef49ca21a5b32b7184a718cb9110ddc5269b06be0c3e3167467df639.
  • Exact attacker input: bundle/logs/payload_identity.txt records the SHA-256 of each pre-generated input. The final tier-2 input has SHA-256 4e3a504e6d390c37a57253a323d3d91382f8ef92caa95a9e2c2193f38a707217; sender logs prove identical byte count/file reuse across vulnerable, patched, and mitigated attempts.
  • Real TCP/product boundary: bundle/logs/receiver_tier2_a1.log and receiver_tier2_a2.log identify loaded TcpSocketServer, ObjectInputStreamLogEventBridge, vulnerable API/Core jars, and Commons Collections; they then show binding, connection acceptance, socket details, and the deserialized event.
  • Command execution: bundle/logs/tier2_rce_marker_a1.txt contains token RCE-1787737383615632389-15376, shell_pid=39677, and parent_pid=39626; attempt a2 contains the same payload token but distinct shell_pid=39759 and parent_pid=39708. Both include uid=1000(vscode), proving execution in two fresh receiver contexts.
  • Direct control: bundle/logs/receiver_control.log shows ObjectInputStreamLogEventBridge.logEvents() rejecting unwrapped poc.GadgetOnly through FilteredObjectInputStream.resolveClass().
  • Fixed controls: bundle/logs/receiver_fixed_a1.log and receiver_fixed_a2.log show TCP acceptance followed by InvalidObjectException: Class is not allowed for deserialization: java.rmi.MarshalledObject; the shared command target is absent.
  • Mitigation: bundle/logs/receiver_mitigation.log shows the same TCP/readObject path failing with InvalidClassException: filter status: REJECTED and no marker.
  • Digest closure: bundle/repro/runtime_manifest.json binds 29 finalized proof artifacts to SHA-256 digests and records entrypoint_kind=tcp_peer, service/health/path success, and full target/runtime identity.

Recommendations / Next Steps

Remove java.rmi.MarshalledObject from the default Log4j deserialization allowlist and avoid unfiltered MarshalledObject.get() for event messages; use a filtered wrapped-object format instead. Upgrade to the first vendor release containing the final upstream correction once published. Do not expose Java serialized-event listeners to untrusted networks. As defense in depth, configure a JEP 290 class filter rejecting java.rmi.MarshalledObject, remove unnecessary gadget libraries, and add regression tests that replay a malicious event through the real TCP receiver and require fail-closed rejection.

Additional Notes

The final script was executed successfully twice consecutively after all amendments. Every execution uses isolated receiver JVMs and randomized ports, removes prior proof artifacts, generates a fresh payload token, and verifies exact payload-byte reuse across vulnerable and controls. Service startup, TCP health, and target-path reachability are tracked independently, and a failed run preserves digest-bound evidence from completed phases. The launcher does not implement a socket, parser, or readObject() path; it only selects serialized mode through TcpSocketServer.createSerializedSocketServer().

GHSA-LOG4J2-4255-MARSHALLEDOBJECT Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:005:07
0:01
session startedaccounts/fireworks/models/kimi-k3 · GHSA-LOG4J2-4255-MARSHALLEDOBJECT · REPRO-20
0:08
0:09
0:49
0:49
extract_facts
no facts extracted
0:52
0:52
supportclaim_contract
0:59
0:59
0:59
1:03
1:04
1:04
1:11
1:11
1:11
1:11
1:16
1:16
1:24
1:24
1:25
$ls /pruva/project-cache 2>/dev/null; ls /pruva/project-cache/repo-mirrors 2>/dev/null; which java javac mvn; java -version 2>&1; python3 --version; curl -sI --max-time 8 https://repo1.maven.org/maven2/ | head -3
0.6s
repo-mirrors
pruva-command: 1: java: not found
Python 3.14.4
HTTP/2 200 
date: Wed, 26 Aug 2026 08:37:03 GMT
content-type: text/html
1:30
1:31
$ls -la /pruva/project-cache/repo-mirrors; cat /pruva/project-cache/.pruva/cache_manifest.json 2>/dev/null; apt-cache policy openjdk-17-jdk-headless 2>/dev/null | head -5; whoami; sudo -n true && echo sudo-ok
0.7s
total 0
drwx------ 2 vscode vscode 40 Aug 26 08:35 .
drwx------ 4 vscode vscode 80 Aug 26 08:35 ..
{
  "schema_version": 1,
  "entries": [
    {
      "path": "repo-mirrors",
1:40
$sudo apt-get update -qq 2>&1 | tail -2 && apt-cache search openjdk | grep -i jdk | head -10
4.9s
openjdk-25-dbg - Java runtime based on OpenJDK (debugging symbols)
openjdk-25-jdk - OpenJDK Development Kit (JDK)
openjdk-25-jdk-headless - OpenJDK Development Kit (JDK) (headless)
openjdk-25-jre - OpenJDK Java runtime, using Hotspot JIT
openjdk-25-jre-headless - OpenJDK Java runtime, using Hotspot JIT (headless)
openjdk-25-source - OpenJDK Development Kit (JDK) source files
jtreg - Regression Test Harness for the OpenJDK platform
jtreg6 - Regression Test Harness for the OpenJDK platform
4:29
5:07
$sudo apt-get install -y -qq openjdk-25-jdk-headless unzip >/tmp/jdk_install.log 2>&1; tail -2 /tmp/jdk_install.log; which java javac; java -version 2>&1
38.0s
update-alternatives: using /usr/lib/jvm/java-25-openjdk-amd64/bin/serialver to provide /usr/bin/serialver (serialver) in auto mode
update-alternatives: using /usr/lib/jvm/java-25-openjdk-amd64/bin/jhsdb to provide /usr/bin/jhsdb (jhsdb) in auto mode
/usr/bin/java
/usr/bin/javac
openjdk version "25.0.4" 2026-07-21
OpenJDK Runtime Environment (build 25.0.4+7-1-26.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 25.0.4+7-1-26.04-Ubuntu, mixed mode, sharing)
08 · How to Fix

How to Fix GHSA-LOG4J2-4255-MARSHALLEDOBJECT

Upgrade org.apache.logging.log4j:log4j-core · maven to none yet - upstream issue open, waiting-for-maintainer label; no CVE/GHSA assigned or later.

Coming soon

Step-by-step mitigation and hardening guidance for GHSA-LOG4J2-4255-MARSHALLEDOBJECT — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: GHSA-LOG4J2-4255-MARSHALLEDOBJECT

Is GHSA-LOG4J2-4255-MARSHALLEDOBJECT exploitable?

Yes. Pruva independently reproduced GHSA-LOG4J2-4255-MARSHALLEDOBJECT in org.apache.logging.log4j:log4j-core and verified the exploit fires end-to-end in a sandboxed environment. A runnable proof-of-concept script and the full agent transcript are on this page (reproduction REPRO-2026-00338).

How severe is GHSA-LOG4J2-4255-MARSHALLEDOBJECT?

GHSA-LOG4J2-4255-MARSHALLEDOBJECT is rated critical severity.

What type of vulnerability is GHSA-LOG4J2-4255-MARSHALLEDOBJECT?

GHSA-LOG4J2-4255-MARSHALLEDOBJECT is classified as CWE-502 (Deserialization of Untrusted Data), a RCE vulnerability.

Which versions of org.apache.logging.log4j:log4j-core are affected by GHSA-LOG4J2-4255-MARSHALLEDOBJECT?

org.apache.logging.log4j:log4j-core log4j-api 2.11.0-2.26.1; log4j-core 2.8.0-2.26.1 (verified against official 2.26.1 jars from Maven Central) is affected by GHSA-LOG4J2-4255-MARSHALLEDOBJECT.

Is there a fix for GHSA-LOG4J2-4255-MARSHALLEDOBJECT?

Yes. GHSA-LOG4J2-4255-MARSHALLEDOBJECT is fixed in org.apache.logging.log4j:log4j-core none yet - upstream issue open, waiting-for-maintainer label; no CVE/GHSA assigned. Upgrading to the fixed version remediates the issue.

How can I reproduce GHSA-LOG4J2-4255-MARSHALLEDOBJECT?

Pruva provides a verified reproduction script on this page. Download it and run it inside an isolated environment such as a container or virtual machine — never against production. The reproduction was confirmed end-to-end by Pruva's automated agents.

Is the GHSA-LOG4J2-4255-MARSHALLEDOBJECT reproduction verified?

Yes. Pruva reproduced GHSA-LOG4J2-4255-MARSHALLEDOBJECT with high confidence in a sandboxed environment, capturing the full agent transcript and artifacts as evidence.
11 · References

References for GHSA-LOG4J2-4255-MARSHALLEDOBJECT

Authoritative sources for GHSA-LOG4J2-4255-MARSHALLEDOBJECT — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.