CVE-2026-40901: DataEase: Quartz JobStore Java deserialization RCE via QRTZ_JOB_DETAILS
CVE-2026-40901 is verified against dataease · github affected versions: <= v2.10.20 fixed version: v2.10.21 vulnerability class: RCE This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00167.
pruva-verify REPRO-2026-00167 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00167/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh DataEase uses the Quartz scheduler with the JDBC JobStore backend so its
periodic tasks (refresh datasets, send digest emails, run maintenance) survive
restarts. Quartz persists each job's JobDataMap in the
qrtz_job_details.JOB_DATA column as a Java-serialized blob and calls
ObjectInputStream.readObject() on that blob every time the trigger fires.
The DataEase classpath ships a version of commons-collections that contains
the well-known transformer-based gadget chain. The only thing standing
between an attacker and code execution is the table contents — and the
preceding step in the chain (CVE-2026-40900, stacked SQL injection) hands
that to them. With write access to a single row of qrtz_job_details, the
next scheduler tick deserializes the attacker's payload and runs whatever
method chain it encodes in the JVM running the DataEase backend.
This is the terminal step of the 4-CVE chain (auth bypass → blocklist bypass → stacked SQLi → Quartz deserialization RCE). The end result is code execution inside the DataEase container as the DataEase process user (root, in the default container image).
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support triages the advisory · repro reproduces it · vuln_variant confirms the fix blocks it · judge verifies.
Loading session...
Scripts, logs, diffs, and output captured during the reproduction.