FasterXML's jackson-databind — the JSON data-binding library embedded in a large share of the Java ecosystem, from Spring Boot to countless internal microservices — shipped a fix in version 2.9.9.2 for CVE-2019-12384, a polymorphic-typing gadget chain that lets an attacker who controls JSON input coerce the deserializer into instantiating ch.qos.logback.core.db.DriverManagerConnectionSource from Logback. Because that class opens a JDBC connection using attacker-supplied driver class names and connection URLs during deserialization, an attacker can point it at a malicious or attacker-controlled database endpoint. Depending on the JDBC driver reachable on the classpath (H2's CREATE TRIGGER capability is the classic example), that connection can be escalated into arbitrary code execution on the host running the vulnerable service — not just a crash or information leak. This is one entry in a long-running family of jackson-databind "gadget chain" deserialization bugs, and it is a useful case study because it shows exactly how a data-binding convenience feature — polymorphic typing — becomes a remote code execution primitive when it's enabled against untrusted input.
What's actually going wrong: polymorphic typing as an RCE primitive
Jackson's default behavior binds incoming JSON directly to a known, statically declared type, which is safe. The danger appears when an application enables polymorphic type handling — via ObjectMapper.enableDefaultTyping(), @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS), or equivalent configuration — so that the JSON payload itself can specify which concrete class to instantiate for a field typed as Object or an abstract base type. That's a legitimate and common pattern for building extensible APIs, but it also means the attacker gets to choose the class, not just the data.
Jackson doesn't execute arbitrary code just by instantiating a class, but Java classes with interesting side effects in their constructors, setters, or readObject/finalize methods can be abused to produce real impact — network callouts, file writes, JNDI lookups, or, as with CVE-2019-12384, JDBC connections that some drivers can turn into code execution. These "gadget classes" don't need to belong to jackson-databind itself; they just need to be present somewhere on the application's classpath, commonly pulled in transitively by logging frameworks, connection pools, or other everyday dependencies. FasterXML maintains a growing denylist of known-dangerous classes inside jackson-databind (BeanDeserializerFactory's blocked-class list) specifically to blunt this class of attack, and CVE-2019-12384 is the entry that added the Logback DriverManagerConnectionSource gadget to that list after it was reported.
Affected versions and components
- jackson-databind: all versions prior to 2.9.9.2 are affected.
- Trigger condition: the application must have polymorphic/default typing enabled somewhere in its
ObjectMapperconfiguration (enableDefaultTyping(),activateDefaultTyping(), or a@JsonTypeInfoannotation usingId.CLASS/Id.MINIMAL_CLASSon a sufficiently generic base type) and accept JSON from an untrusted source into that binding path. - Gadget dependency:
ch.qos.logback.core.db.DriverManagerConnectionSource, shipped in logback-core, must be reachable on the application's classpath — it doesn't need to be used anywhere in application code, only present. - Real-world impact ceiling: dependent on which JDBC drivers are also on the classpath. H2, and certain configurations of other embedded/JDBC drivers, can turn the resulting database connection into arbitrary code execution; where no such driver is present, impact may be limited to SSRF-style outbound connections or denial of service.
- Because Logback ships as a transitive dependency of Spring Boot, Spring Cloud, and a very large number of Java server frameworks, "logback isn't on our classpath" is a weaker assumption than most teams expect — it's worth verifying rather than asserting.
CVSS, EPSS, and KEV context
NVD lists CVE-2019-12384 with a CVSS v3.1 base score of 7.5 (High), scored along the vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — reflecting NVD's convention of treating unauthenticated, network-exploitable jackson-databind gadget bugs primarily as availability/denial-of-service issues at the scoring level. That score materially understates practical risk: in classpath configurations where an exploitable JDBC driver is present, this bug is a full remote-code-execution primitive, and security teams should treat it accordingly rather than anchoring on the base score alone. As with the rest of the jackson-databind gadget-chain family, EPSS-predicted exploitation probability should be checked against current data at exploit-scoring time (first.org) rather than treated as a fixed number in this writeup, since EPSS is recalculated continuously and jackson deserialization bugs as a class have seen renewed scanning interest whenever new gadgets or public PoCs surface. CVE-2019-12384 does not currently appear on CISA's Known Exploited Vulnerabilities (KEV) catalog, but that should not be read as "safe to deprioritize" — it sits inside a dependency (jackson-databind's default-typing gadget surface) that has produced multiple other CVEs that attackers have actively chained against internet-facing Java services, and unpatched instances remain a favorite target for automated deserialization scanners.
Timeline
- 2017: FasterXML begins actively maintaining a blocklist of known-dangerous classes inside jackson-databind after the original wave of polymorphic-typing gadget chain disclosures (starting with CVE-2017-7525 and related c3p0/Groovy/Spring gadgets), establishing the pattern of "one CVE per newly discovered gadget class" that continues today.
- 2018–2019: Researchers continue to identify additional gadget classes across the Java ecosystem (Spring, Groovy, MyBatis, Ehcache, and others), each triaged and blocklisted under its own CVE as FasterXML's denylist-based mitigation model plays whack-a-mole with newly discovered gadgets.
- July 2019: FasterXML ships jackson-databind 2.9.9.2, adding
ch.qos.logback.core.db.DriverManagerConnectionSourceto the blocked-class list and formally assigning CVE-2019-12384. - 2019–2020: Related CVEs (e.g., CVE-2019-12814, CVE-2019-14379, CVE-2019-16335, CVE-2019-16942/16943, CVE-2019-17267, CVE-2020-8840, CVE-2020-9546, CVE-2020-10650, and others) continue to expand the denylist as additional gadgets are reported, underscoring that denylisting individual classes is a mitigation, not a structural fix, for applications that leave default typing enabled.
- Present: jackson-databind has moved toward safer defaults and stronger guidance against enabling global default typing at all; the durable fix for this entire vulnerability class is architectural — disable polymorphic typing against untrusted input — rather than relying on the current state of any denylist.
Remediation steps
- Upgrade jackson-databind to 2.9.9.2 or later (and ideally to the current supported 2.x line) across every service and every transitive dependency that bundles its own copy — dependency convergence audits matter here, since a single outdated shaded or vendored copy is enough to leave a service exploitable.
- Audit every
ObjectMapperconfiguration in your codebase forenableDefaultTyping(),activateDefaultTyping(), or@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)/Id.MINIMAL_CLASSusage against any type that ultimately resolves toObjector a broad interface. If global default typing is enabled, disable it and switch to an explicit, closed@JsonSubTypesallowlist for the specific subtypes your API actually needs. - Prefer
PolymorphicTypeValidator(available in newer Jackson releases) to enforce an explicit allowlist of base types eligible for polymorphic deserialization, rather than relying solely on FasterXML's blocklist, which by definition can only block gadgets that have already been discovered and reported. - Inventory your classpath for gadget-capable dependencies — logback-core, c3p0, various JDBC drivers, Groovy, and templating engines are recurring offenders. Removing unused transitive dependencies (especially JDBC drivers not actually needed by a given service) shrinks the exploitable gadget surface even if a future undisclosed gadget is found.
- Treat all externally reachable JSON deserialization endpoints as untrusted input boundaries — apply strict content-type validation, schema validation ahead of deserialization where feasible, and network egress controls so that even a successful gadget instantiation can't reach an attacker-controlled JDBC endpoint or make outbound connections at all.
- Re-scan and re-test after upgrading, since some frameworks and internal libraries pin jackson-databind versions independently of your top-level
pom.xml/build.gradledeclarations, and a naive dependency bump can silently fail to take effect due to a nearer, older version winning dependency resolution.
How Safeguard Helps
Vulnerability scanners will happily flag every service that merely has jackson-databind below 2.9.9.2 on its classpath, but that tells a security team almost nothing about which of those findings actually matter — CVE-2019-12384 only becomes exploitable when default typing is enabled and a usable gadget like Logback's DriverManagerConnectionSource is reachable from that same deserialization path. Safeguard's reachability analysis traces call paths from your actual application code down through the dependency graph to determine whether the vulnerable deserialization sink is reachable from an externally exposed entry point, so teams can separate "patch this today" from "patch on the normal cadence" instead of treating every hit as equally urgent. Griffin AI layers on top of that analysis to explain, in plain language, how a specific gadget chain would need to be triggered in your codebase and what code change actually closes the gap — not just which version number to bump. Continuous SBOM generation and ingest keep an accurate, queryable inventory of every jackson-databind instance (including shaded and transitive copies) across your services, so "we already fixed this everywhere" is a verifiable claim rather than an assumption. And where the fix is a straightforward version bump or an ObjectMapper hardening change, Safeguard can open an auto-fix pull request directly, cutting the time between disclosure and a merged remediation from a security-team task list to a review click.