Security teams running Java services with FasterXML jackson-databind got another reminder in late 2020 that "we already patched Jackson deserialization" is rarely the end of the story. CVE-2020-36189 is one of a cluster of gadget-chain vulnerabilities patched in jackson-databind 2.9.10.8 that allows remote code execution, server-side request forgery, or XML external entity (XXE) style attacks when an application performs polymorphic JSON deserialization and has the JDOM / JDOM2 XML library on its classpath. An attacker who can influence JSON sent to a vulnerable deserialization endpoint can smuggle in a type reference to org.jdom2.transform.XSLTransformer, instructing the target application to fetch and apply an attacker-controlled XSLT stylesheet — a primitive that XSLT processors like Xalan can turn into arbitrary Java method invocation, effectively RCE, on top of the more immediately obvious SSRF/XXE impact.
If that description sounds familiar, it's because this is a bypass of an earlier fix. jackson-databind has shipped a running "blacklist" of dangerous classes since 2017, and the JDOM transform gadget was first blocked under CVE-2019-14540. CVE-2020-36189 exists because the original blocklist entry didn't fully account for the JDOM2 variant of the class, leaving a functionally identical attack path open for any service that had upgraded believing the earlier CVE closed the door. It's a textbook illustration of why blocklist-based deserialization defenses age poorly, and why supply chain teams need to track transitive dependency exposure, not just a single library's version number.
How the gadget chain works
jackson-databind's polymorphic deserialization feature lets a JSON payload declare, via an embedded type identifier (commonly @class or @type), which concrete Java class the library should instantiate to hold a given value. This is intentional and useful when an application defines a tightly-scoped set of expected subtypes. It becomes dangerous when:
- The application enables global default typing (
ObjectMapper.enableDefaultTyping()/activateDefaultTyping()), or annotates a field with@JsonTypeInfo(use = Id.CLASS)without restricting which classes are acceptable, and - A "gadget" class exists on the runtime classpath whose constructor or setters can be abused to trigger unwanted side effects purely by being instantiated and populated with attacker-supplied fields.
For CVE-2020-36189, the gadget is org.jdom2.transform.XSLTransformer. Constructing it with an attacker-controlled stylesheet reference and then invoking it against an XML source causes the JVM to fetch and execute that stylesheet. Because XSLT processors commonly used in the Java ecosystem (Xalan in particular) support extension functions, a malicious stylesheet can be crafted to reach arbitrary static methods — turning a "just apply this transform" primitive into full remote code execution. Even where an environment blocks the RCE extension path outright, the same gadget can be used to force the server to make outbound requests to attacker-chosen URLs (SSRF) or to leak local file contents through XXE-style constructs.
None of this requires a memory-corruption bug or a clever new deserialization primitive — it requires only that (a) untrusted JSON reaches an ObjectMapper configured for polymorphic typing, and (b) jdom or jdom2 sits somewhere in the dependency tree, even indirectly, even unused in the code paths a developer actually wrote.
Affected versions and components
- jackson-databind: 2.0.0 through 2.9.10.7 are affected. The fix landed in 2.9.10.8, with corresponding fixes backported to the 2.10.x and 2.11.x lines (2.10.5.1, 2.11.4) and carried forward into 2.12.0 and later.
- Trigger condition: the application must use jackson-databind's default/polymorphic typing (global
enableDefaultTyping/activateDefaultTyping, or unrestricted@JsonTypeInfo(use = Id.CLASS)/Id.MINIMAL_CLASS) on a code path that deserializes attacker-influenced JSON. - Gadget dependency:
org.jdom:jdomororg.jdom:jdom2present on the classpath, directly or transitively (frequently pulled in by XML tooling, reporting libraries, or older Spring/Struts-adjacent stacks). - Services that pin jackson-databind to a fixed, unaffected release but never audited why jdom/jdom2 is on the classpath remain exposed to the broader class of "next gadget" issues in this family even after patching this specific CVE.
CVSS, EPSS, and KEV context
NVD scores this issue in the High range, consistent with the rest of the December 2020 jackson-databind gadget batch — CVSS v3.1 base score of roughly 8.1 (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H). The "High" attack complexity reflects that exploitation isn't zero-click against every jackson-databind consumer: it requires the specific misconfiguration (default/global typing enabled) plus the specific gadget dependency (jdom/jdom2) to be present together. EPSS scoring for this CVE sits low, in line with most of the 2020 jackson-databind blocklist-bypass batch — there's no widespread evidence of active mass exploitation, and it does not appear on CISA's Known Exploited Vulnerabilities (KEV) catalog as of this writing. That combination — real RCE potential, but conditional on configuration and a low observed-exploitation signal — is exactly the profile that tends to get deprioritized in a vulnerability backlog, which is the risk: EPSS and KEV absence tell you what attackers are doing today, not whether your specific deployment satisfies the trigger conditions.
Timeline
- 2019 — The original JDOM gadget chain is identified and blocked via a blacklist entry in jackson-databind, tracked as CVE-2019-14540.
- December 2020 — FasterXML ships jackson-databind 2.9.10.8, extending the deserialization blocklist to cover a large batch of previously-missed gadget classes across multiple libraries, including the JDOM2 variant that had bypassed the 2019 fix. Corresponding fixes are backported into the 2.10.5.1 and 2.11.4 maintenance releases.
- Early 2021 — Individual CVE identifiers, including CVE-2020-36189, are published against the December 2020 blocklist batch, giving each affected gadget class its own tracking record for downstream vulnerability management and SCA tooling.
- Present — The CVE remains a common finding in software composition analysis scans of Java services carrying older jackson-databind and jdom/jdom2 versions, particularly in long-lived internal services that never revisited default-typing configuration decisions made years earlier.
Remediation steps
- Upgrade jackson-databind. Move to 2.9.10.8 or later on the 2.9.x line, or to 2.10.5.1+, 2.11.4+, or 2.12.0+ on newer lines. Treat this as a floor, not a target — staying current on the latest 2.x release picks up subsequent blocklist additions for free.
- Eliminate global default typing. Audit for
ObjectMapper.enableDefaultTyping()/activateDefaultTyping()calls and remove them where possible. If polymorphic deserialization is a genuine requirement, scope it with@JsonTypeInfoon specific fields rather than applying it globally. - Use an explicit allow-list validator. Where polymorphic typing is required, configure a
PolymorphicTypeValidator(Jackson's supported replacement for blocklist-based safety since 2.10) that only permits deserialization into a known-safe base type and its intended subtypes — never "any class on the classpath." - Audit and prune the JDOM/JDOM2 dependency. Confirm whether
org.jdom:jdomororg.jdom:jdom2is actually required at runtime. If it was pulled in transitively by a library that doesn't need its XSLT capabilities, exclude it or replace the dependency with a narrower alternative. - Generate or refresh your SBOM and re-scan transitive dependencies. This CVE is a reminder that gadget risk lives in combinations of dependencies, not any single library in isolation — a full, current software bill of materials is the only reliable way to know both jackson-databind's version and whether jdom/jdom2 rides along with it.
- Add regression coverage. Once remediated, add a test (or a CI policy check) asserting that default typing is not re-enabled and that disallowed gadget classes remain unreachable from deserialization entry points, so the fix survives future refactors.
How Safeguard Helps
This vulnerability is a case study in why version-matching alone produces noisy, low-signal findings: the mere presence of an old jackson-databind release doesn't tell you whether the dangerous configuration and the JDOM gadget are actually both present and reachable in your build. Safeguard's reachability analysis traces whether the vulnerable deserialization path and the org.jdom2.transform.XSLTransformer gadget are genuinely wired together in your call graph, so teams can separate "theoretically affected" from "actually exploitable" and triage accordingly. Griffin AI correlates that reachability signal with how jackson-databind is configured across your services — flagging global default-typing usage and unscoped @JsonTypeInfo annotations that create the precondition for this class of bug. Continuous SBOM generation and ingestion give security and platform teams a live view of exactly which services carry jdom or jdom2 transitively, even when no developer ever imported it directly. And where remediation is confirmed safe, Safeguard can open an auto-fix pull request bumping jackson-databind to a patched release and flagging the unsafe typing configuration for review, cutting the time from detection to a merged, verified fix.