fix(deps): update dependency com.fasterxml.jackson.core:jackson-databind to v2.22.2 [security] - #376
Open
renovate[bot] wants to merge 1 commit into
Open
renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
…ind to v2.22.2 [security]
Contributor
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.22.1→2.22.2jackson-databind: Path Deserialization Missing Scheme Allowlist for FileSystemProvider Resolution
CVE-2026-19032 / GHSA-wjgm-6hv5-3cvf
More information
Details
Summary
A
java.nio.file.Pathfield bound from untrusted JSON reachesJDKFromStringDeserializer.NioPathHelper.deserialize. The attacker string flows throughnew URI(value)→Path.of(uri), then onFileSystemNotFoundExceptioninto aServiceLoader<FileSystemProvider>enumeration that callsprovider.getPath(uri)on the first scheme-matching provider. No scheme is rejected, so untrusted JSON can drive an arbitrary registered provider under the defaultJsonMapper.builder().build().Impact is bounded. The JDK built-in providers (
file,jar/zipfs) do no network I/O and do not mount, so the path is inert without a side-effecting third-party provider. BindingPathfrom untrusted input is already an anti-pattern.Description
NioPathHelper.deserializeperforms provider resolution driven by the attacker URI (abridged; the real method also handles a Windows drive-letter prefix and wraps failures viactxt.handleInstantiationProblem(...)):The attacker's scheme selects the provider and the attacker's URI is passed to it; the enumeration also forces provider classloading during
readValue. For built-in schemes likejar:,getPaththrowsFileSystemNotFoundException(a mount requires explicitnewFileSystem), surfacing as a wrappedValueInstantiationExceptionwith no terminal effect. Any mount, network I/O, or resource access depends entirely on the selected provider.Vulnerable Code Location
src/main/java/tools/jackson/databind/deser/jdk/JDKFromStringDeserializer.javaSTD_PATH→NioPathHelper.deserialize;NioPathHelper.deserializebody(
new URI→Path.of(uri)→ServiceLoader.load(FileSystemProvider.class)→provider.getPath(uri)).Proof of Concept
Two PoCs are provided.
PoC 1 — sink reached (built-in
jarprovider).com/poc/Vuln04_PathProvider.java:PoC 2 — scheme-selection mechanism demo (custom
FileSystemProvider).A third-party provider (scheme
evilscheme) registered viaMETA-INF/services/java.nio.file.spi.FileSystemProvider, which is standing in for any provider a real application ships.com/poc/EvilFileSystemProvider.java:Registration descriptor —
src/main/resources/META-INF/services/java.nio.file.spi.FileSystemProvider:Driver —
com/poc/Vuln04b_PathProviderMount.java:Execution Steps
The PoCs need only the three Jackson 3.2.1 jars on the classpath and can be built with plain
javac/java. PoC 2 additionally requires theMETA-INF/servicesdescriptor to be on the runtime classpathReproduction Evidence
Executed against jackson-databind 3.2.1 (OpenJDK 25).
PoC 1 :
Notes: the JDK built-in
jarprovider'sgetPathdoes not auto-mount (it also throwsFileSystemNotFoundException, since onlynewFileSystemmounts). PoC 1 proves the in-scope defect: attacker input reaches the scheme-drivenServiceLoaderresolution duringreadValuewith no allow-list. PoC 2 only illustrates the downstream mechanism.PoC 2 :
Purely from a JSON string, jackson's
ServiceLoaderfallback selected the attacker-named scheme's provider and invokedprovider.getPath(uri)with the full attacker URI insidereadValue. Whether a given provider then does anything harmful is outside the library's control; the in-scope issue is the absence of a scheme restriction before this fallback runs.Impact
Untrusted JSON drives
provider.getPath(attackerURI)on an attacker-chosen provider duringreadValue. With only the JDK built-in providers this is inert. Real impact requires a side-effecting third-party provider on the classpath. The fix is to close thescheme-restriction gap.
Recommended Fix
jar:and other schemes viactxt.handleWeirdStringValue(...). A hard-coded set keeps the fix backport-safe with no new configuration surface.ServiceLoader<FileSystemProvider>enumeration for disallowed schemes, so untrusted JSON cannot select and drive an arbitrary registered provider.java.nio.file.Path-typed fields should not be bound from untrusted JSON.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
jackson-databind: Duration XMLGregorianCalendar Unbounded Number Parse DoS
CVE-2026-68497 / GHSA-q4xh-88c3-wmh7
More information
Details
Summary
jackson-databind3.2.1 deserializes a JSON string bound to ajavax.xml.datatype.Durationorjavax.xml.datatype.XMLGregorianCalendarfield by passing the raw string verbatim toDatatypeFactory.newDuration(value)/newXMLGregorianCalendar(value). Per the XML-Schema lexical grammar these factory methods accept numeric components of arbitrary length, which the JDK materializes intojava.math.BigInteger/BigDecimalusing the nativeBigInteger(String)constructor (an O(n²) parser). Because the digits reside inside a JSON string token, jackson-core'sStreamReadConstraints.maxNumberLengthguard (which bounds only JSON number tokens) never fires, so there is no length limit anywhere on this path. An unauthenticated attacker can submit a single small request (e.g. ~1–5 MB) that forces tens of seconds to minutes of single-thread CPU consumption, yielding a denial of service under the defaultJsonMapper.builder().build()mapper with no polymorphic typing or special configuration.Details
StreamReadConstraints.maxNumberLength(jackson-core, default 1000) bounds the text length of JSON number tokens only; it does not apply to digits inside a JSON string token (maxStringLengthdefault is 100,000,000). jackson's own value binders compensate for this gap elsewhere —NumberDeserializersexplicitly callstreamReadConstraints().validateIntegerLength(text.length())/validateFPLength(text.length())before parsing a stringified number (NumberDeserializers.java:1063,:1139). The XML-datatype deserializer omits this identical pre-check.CoreXMLDeserializersregistersStddeserializers by default for any field typedjavax.xml.datatype.DurationorXMLGregorianCalendar(findBeanDeserializer), with no opt-in required.Std._deserializehands the attacker string straight to the datatype factory:Per the XSD lexical rules,
newDurationparses each numeric component (years, months, …) into aBigInteger, andnewXMLGregorianCalendarparses fractional seconds into aBigDecimal. The JDK uses the nativeBigInteger(String)/BigDecimal(String)constructors, which are O(n²) in the digit count. A short JSON string such as"P" + "9"×N + "Y"therefore forces the allocation and O(N²) parse of an N-digitBigInteger, entirely downstream of every jackson-core constraint.Vulnerable Code Location
src/main/java/tools/jackson/databind/ext/CoreXMLDeserializers.java:137—
newDuration(value)(TYPE_DURATION)src/main/java/tools/jackson/databind/ext/CoreXMLDeserializers.java:147—
newXMLGregorianCalendar(value)(TYPE_G_CALENDAR fallback)src/main/java/tools/jackson/databind/ext/CoreXMLDeserializers.java:42-46(
findBeanDeserializerreturnsStdforXMLGregorianCalendar/Duration)src/main/java/tools/jackson/databind/deser/jdk/NumberDeserializers.java:1063,1139Proof of Concept
PoC source (
Vuln07_DurationDoS.java). It uses only the publicObjectMapper.readValueAPI and a default mapper; the only "special" element is a normal DTO exposing ajavax.xml.datatype.Durationfield.Minimal HTTP-shaped payload (what an attacker sends):
{ "ttl": "P99999999999999999999…9Y" } // 'P' + N nines + 'Y', N up to ~100,000,000An
XMLGregorianCalendarfield is equally affected via the fractional-seconds path, e.g.{ "at": "0000-01-01T00:00:00." + "9"×N }.Execution Steps
The PoC needs only the three Jackson 3.2.1 jars on the classpath; it can be built and run with plain
javac/java(no Maven required). The jars are the standard published artifacts (here resolved from the local Maven cache~/.m2, but any copy works).The
digitssystem property controls the number of9characters in the year component; JSON payload size ≈ digits + 12 bytes. Increase toward the default 100,000,000maxStringLengthto scale cost further.Environment used for the evidence below: jackson-databind 3.2.1, jackson-core 3.2.1, jackson-annotations 2.22; OpenJDK 25 on macOS (darwin), default
JsonMapper.builder().build().Reproduction Evidence
Deterministic values (payload byte count, resulting bit-length) are exact across runs; timings vary with load. Two independent runs at different sizes:
digits = 5,000,000 (~5 MB payload):
digits = 1,000,000 (~1 MB payload, for fast repeatability):
Interpretation: a normal
"P1Y"value parses in tens of milliseconds; a ~1 MB attacker payload consumes ~11 s and a ~5 MB payload ~293 s of single-thread CPU — a 5–6 order-of-magnitude amplification. The super-linear growth (≈26× cost for 5× payload) is consistent with the JDK's O(n²)BigInteger(String)constructor. The cost occurs insideDatatypeFactory.newDuration, downstream of jackson-core'sStreamReadConstraints(independently confirmed: the same digit sequence supplied as a bare JSON number token is rejected withStreamConstraintsException, whereas inside a string token it is not bounded).Impact
An unauthenticated attacker can stall a request-processing thread for tens of seconds to minutes and allocate a large
BigInteger/BigDecimalfrom a single small request. Because the cost is CPU-bound and super-linear, a handful of concurrent requests can saturate the server's worker threads and CPU, denying service to all users. The exposure requires only that a bound type expose ajavax.xml.datatype.DurationorXMLGregorianCalendarfield common in applications that ingest XML-schema derived data, SOAP/JAXB-adjacent models, or configuration carrying XSD durations — and fires under the default mapper with no polymorphic typing.Recommended Fix
Apply the same validate-length-then-parse idiom the core
NumberDeserializersalready use:CoreXMLDeserializers.Std._deserialize, enforce a maximum raw-string length beforecalling
newDuration(value)/newXMLGregorianCalendar(value)— e.g. reject inputslonger than
ctxt.streamReadConstraints().getMaxNumberLength()(or a dedicated bound),routing over-length input through
ctxt.handleWeirdStringValue(...).of each numeric component before delegating to
DatatypeFactory.Duration/XMLGregorianCalendarfields bound from untrusted input mustbe length-limited at the transport layer.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
jackson-databind: Comparable missing from DefaultBaseTypeLimitingValidator's unsafe base types (incomplete PolymorphicTypeValidator denylist)
CVE-2026-83557 / GHSA-gx83-3vf8-gh7j
More information
Details
Summary
DefaultBaseTypeLimitingValidator— thePolymorphicTypeValidatorused automatically whenever@JsonTypeInfois applied without an explicitly configured custom validator — denies polymorphic resolution only for nine specific "unsafe base types" (Object,Serializable,Closeable,AutoCloseable,Cloneable,Runnable,java.util.logging.Handler,javax.naming.Referenceable,javax.sql.DataSource). ItsisSafeSubType()returnstrueunconditionally for every other base type.java.lang.Comparableis not in that list, despite being implemented by a very large fraction of JDK and application classes — comparable in breadth toSerializable, which is denylisted for exactly that reason. An application with an@JsonTypeInfo-annotatedComparable-typed property, and no custom validator configured, will accept a type identifier for essentially any class implementingComparable.Details
Affected file:
src/main/java/tools/jackson/databind/jsontype/DefaultBaseTypeLimitingValidator.javaThe class's own JavaDoc acknowledges the design ("Note that when using potentially unsafe base type like
java.lang.Objecta custom implementation... is needed"), so the trade-off of leaving broad base types unrestricted is intentional. The gap is thatComparablehas the same breadth of implementers as the types this class does restrict, and its absence looks like an oversight rather than a deliberate choice — consistent with the ongoing, incremental nature of this list (Runnablewas added recently for issue #5014).This is specific to the default, unconfigured validator reached via bare
@JsonTypeInfousage. Global "Default Typing" viaactivateDefaultTyping()is not affected, because that method structurally requires an explicitPolymorphicTypeValidatorargument — a correctly-configuredBasicPolymorphicTypeValidatorrejects the same payload underactivateDefaultTyping().PoC
Built entirely from source (jackson-databind + jackson-core + jackson-annotations,
javac, OpenJDK 21, no third-party gadget libraries, no network access):1. Sanity check (benign class, confirms the mechanism fires):
2. Real JDK class substitution:
3. Negative control — Default Typing with an explicit custom PTV:
Observed output:
$ java -cp .:build/classes PtvGapTest3
Trying: {"value":["java.io.File","/etc/passwd"]}
ACCEPTED, class=java.io.File value=/etc/passwd
$ java -cp .:build/classes PtvGapTest4
Trying malicious substitution: ["PtvGapTest4$Holder",{"value":["java.io.File","/etc/passwd"]}]
REJECTED - InvalidTypeIdException: Could not resolve type id 'java.io.File' as a
subtype of java.lang.Comparable: Configured PolymorphicTypeValidator denied resolution
Impact
Any application declaring an
@JsonTypeInfo-annotated property or class withComparableas its base type, without a separately configured restrictivePolymorphicTypeValidator, will accept a type identifier for essentially any class implementingComparable. Concrete impact is demonstrated viajava.io.File: an attacker can cause construction of aFileobject for an arbitrary, attacker-chosen path. On its own this is a controlled-object-instantiation primitive; if the application later calls path-sensitive or mutating methods on the received value, this becomes a path-traversal-adjacent primitive.Suggested remediation:
java.lang.ComparabletoUnsafeBaseTypes.UNSAFE.java.lang.Iterable,java.util.EventListener) for the same gap.isSafeSubType()for base types outside the fixed denylist, rather than unconditionaltrue.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:LReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.