{"id":"CVE-2026-59889","kind":"vulnerability","aliases":["CVE-2026-59889","GHSA-5gvw-p9qm-jgwh"],"related":[],"title":"jackson-databind: @JsonView bypassed for @JsonUnwrapped container properties on deserialization","description":"## Summary\n`UnwrappedPropertyHandler.processUnwrapped()` replays the buffered JSON for a `@JsonUnwrapped` property by iterating its properties and calling `prop.deserializeAndSet()` with **no `prop.visibleInView(ctxt.getActiveView())` guard** — the exact guard `processUnwrappedCreatorProperties()` received in the #5971 / GHSA-rcqc-6cw3-h962 fix, and the guard `BeanDeserializer.deserializeWithUnwrapped` applies to directly-matched properties. As a result, a property annotated with both `@JsonView(PrivilegedView.class)` and `@JsonUnwrapped` is written from attacker JSON even when deserializing under a more-restrictive active view.\n\n**Correction to the original framing (runtime-verified):** the gap is NOT a per-field inner `@JsonView` (the unwrapped sub-object's own `BeanDeserializer` gates inner fields correctly). The unchecked gate is the **view of the unwrapped CONTAINER property**.\n\n## Intent proof (runtime, 2.x HEAD 21dd70dd and 3.x HEAD 7a5939d6)\nAn `@JsonView(AdminView)` property that is NOT `@JsonUnwrapped` → `null` under `PublicView` (correctly gated). The identical property WITH `@JsonUnwrapped` → fully populated (bypass). The fix the creator path already received, not applied to the regular-property method.\n\n## Impact — write-side mass-assignment / privilege escalation\n`@JsonView` is commonly used as a write-side authorization guard: a public endpoint binds the body under `readerWithView(PublicView.class)` and groups privileged state in a nested object whose container property is `@JsonView(AdminView)`. When that property is `@JsonUnwrapped`, an untrusted caller mass-assigns it. PoC: a self-service registration where `AccountFlags{role,approved,creditBalance}` is `@JsonView(AdminView) @JsonUnwrapped`; attacker JSON `{role:ADMIN,approved:true,creditBalance:1000000}` under `PublicView` binds all three → approved admin with arbitrary balance. The failing gate is a WRITE gate, hence integrity-high (`C:N/I:H/A:N`); no worse than the C:L/I:L parent and arguably higher as `@JsonView`-as-write-guard is the exact use case #5971/#5969 defended.\n\n## Affected\n- `com.fasterxml.jackson.core:jackson-databind` 2.x: confirmed bypass at 21dd70dd (== released 2.21.4 / 2.22.0 line; includes the #5973 backport). `DEFAULT_VIEW_INCLUSION` default=true.\n- `tools.jackson.core:jackson-databind` 3.x: confirmed bypass at HEAD 7a5939d6 (latest 3.x). `DEFAULT_VIEW_INCLUSION` default=false → the stock-config repro is the common shape where privileged inner fields are individually `@JsonView(PublicView)` and the developer relies on the container `@JsonView(AdminView)`; the 3.x PoC mass-assigns role/approved/creditBalance under PublicView. (The other simultaneous report's PoC was reportedly fixed on 3.x; this distinct container-property path is not.)\n\n## Additive variants (runtime-confirmed both branches; all closed by the same one-line guard)\n- nested `@JsonUnwrapped` (unwrapped-in-unwrapped) — recursive bypass.\n- merge / `readerWithView(...).withValueToUpdate(...)` (PATCH/partial-update) — bypass; non-unwrapped merge control gates correctly.\n- builder-based deserializer (`@JsonDeserialize(builder=...)`) — `BuilderBasedDeserializer` routes through the same `processUnwrapped`.\n- Honest non-findings: read-side serialization correctly honors views (no leak); `@JsonAnySetter`+view and `@JsonTypeInfo`+`@JsonUnwrapped` are separate/unsupported behaviors, not this bug.\n\n## Fix\nAdd `prop.visibleInView(ctxt.getActiveView())` (when `MapperFeature.DEFAULT_VIEW_INCLUSION`/active-view applies) to the `processUnwrapped()` property loop, mirroring `processUnwrappedCreatorProperties()`. One change closes the impact PoC + all three variants across `BeanDeserializer` and `BuilderBasedDeserializer`. Full runnable PoCs (2.x + 3.x) + variant harnesses available on request.","summary":"jackson-databind does not apply @JsonView checks when it replays @JsonUnwrapped container properties during deserialization, so a property hidden from the active view is still written from the request body. An attacker can set privileged fields such as role, approved status or balance on a public endpoint that relies on the view for write protection.","severity":"medium","cvss":6.5,"epss":0.0034600000362843275,"exploited":false,"exploited_at":null,"products":[{"name":"tools.jackson.core:jackson-databind","fixed":["3.1.5"],"affected":">= 3.0.0, <= 3.1.4","ecosystem":"maven"},{"name":"com.fasterxml.jackson.core:jackson-databind","fixed":["2.22.1"],"affected":">= 2.22.0, < 2.22.1","ecosystem":"maven"},{"name":"tools.jackson.core:jackson-databind","fixed":["3.2.1"],"affected":">= 3.2.0, < 3.2.1","ecosystem":"maven"},{"name":"com.fasterxml.jackson.core:jackson-databind","fixed":["2.21.5"],"affected":">= 2.19.0, < 2.21.5","ecosystem":"maven"},{"name":"com.fasterxml.jackson.core:jackson-databind","fixed":["2.18.9"],"affected":">= 2.0.0-RC1, < 2.18.9","ecosystem":"maven"}],"ecosystems":["maven"],"tags":["cwe-863","jackson-databind","java","maven","package","rest-api"],"not_affected_if":["fixed-version","no-jsonview-on-unwrapped","no-readerwithview-binding","read-only-api"],"how_to_check":"Run mvn dependency:tree (or the Gradle equivalent) and check whether jackson-databind resolves to a version in an affected range. Then search the code for @JsonUnwrapped on properties that also carry @JsonView and for readerWithView usage.","fix":"Upgrade jackson-databind to 3.1.5 (3.1.x line), 3.2.1 (3.2.x), 2.22.1 (2.22.x), 2.21.5 (2.21.x) or 2.18.9 (2.18.x). Until then, stop combining @JsonUnwrapped with @JsonView on writable properties.","status":"open","published_at":"2026-07-14T21:17:06+00:00","first_seen_at":"2026-10-23T19:11:32+00:00","triaged_at":"2026-10-23T21:46:14+00:00","updated_at":"2026-10-23T23:44:52+00:00","category":"package","confidence":0.7,"triage":{"at":"2026-10-23T21:46:14Z","model":"claude-haiku-5-5","output":{"fix":"Upgrade jackson-databind to 3.1.5 (3.1.x line), 3.2.1 (3.2.x), 2.22.1 (2.22.x), 2.21.5 (2.21.x) or 2.18.9 (2.18.x). Until then, stop combining @JsonUnwrapped with @JsonView on writable properties.","reach":"internet","impact":"high","summary":"jackson-databind does not apply @JsonView checks when it replays @JsonUnwrapped container properties during deserialization, so a property hidden from the active view is still written from the request body. An attacker can set privileged fields such as role, approved status or balance on a public endpoint that relies on the view for write protection.","category":"package","who_cares":["java","jackson-databind","maven","rest-api"],"confidence":0.7,"needs_auth":"no","worst_case":"Attacker mass-assigns privileged fields like admin role or balance","analyst_note":"","how_to_check":"Run mvn dependency:tree (or the Gradle equivalent) and check whether jackson-databind resolves to a version in an affected range. Then search the code for @JsonUnwrapped on properties that also carry @JsonView and for readerWithView usage.","needs_analyst":false,"not_affected_if":["no-jsonview-on-unwrapped","no-readerwithview-binding","read-only-api","fixed-version"],"user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.001281,"input_tokens":4574,"output_tokens":1647,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-2026':13A,21A '-59889':14A,22A '-863':44B '/active-view':579C '1000000':349C '2':227C,405C,604C '2.21.4':412C '2.22.0':413C '21dd70dd':230C,410C '3':232C,428C,436C,470C,489C,606C '5969':398C '5971':139C,397C '5973':417C '5gvw':17A '6cw3':143C '7a5939d6':235C,434C 'accountflag':334C 'across':597C 'activ':76B,181C 'add':572C 'addit':499C 'admin':345C,356C 'adminview':238C,314C,340C,468C 'affect':400C 'alreadi':262C 'annot':161C 'api':53B 'appli':59B,150C,265C,580C 'approv':94B,336C,346C,355C 'arbitrari':358C 'arguabl':384C 'as-write-guard':388C 'assign':278C,325C,475C 'attack':86B,171C,342C 'author':290C 'avail':610C 'backport':418C 'balanc':97B,359C 'base':537C 'beandeseri':208C,598C 'beandeserializer.deserializewithunwrapped':149C 'behavior':567C 'bind':295C,352C 'bodi':84B,297C 'branch':505C 'buffer':114C 'bug':570C 'builder':536C,540C 'builder-bas':535C 'builderbaseddeseri':541C,600C 'bypass':5A,256C,408C,431C,522C,527C 'c':371C,379C 'call':125C 'caller':322C 'case':396C 'chang':589C 'check':61B 'close':507C,590C 'com.fasterxml.jackson.core':27A,35A,39A,401C 'common':283C,450C 'config':446C 'confirm':407C,430C,503C 'contain':8A,66B,222C,310C,466C,494C 'container-properti':493C 'control':532C 'correct':183C,212C,247C,534C,555C 'creator':260C 'creditbal':337C,348C 'ctxt.getactiveview':130C,574C 'cve':12A,20A 'cwe':43B 'databind':3A,26A,30A,34A,38A,42A,47B,56B,404C,427C 'default':419C,422C,438C,441C 'defend':399C 'deseri':11A,69B,175C,538C 'develop':462C 'direct':153C 'directly-match':152C 'distinct':492C 'endpoint':101B,294C 'escal':280C 'even':173C 'exact':133C,394C 'fail':361C 'fals':442C 'field':90B,198C,211C,455C 'find':550C 'fix':145C,258C,487C,571C 'frame':187C 'full':601C 'fulli':254C 'gap':192C 'gate':209C,215C,248C,362C,366C,533C 'ghsa':16A,141C 'ghsa-5gvw-p9qm-jgwh':15A 'ghsa-rcqc-6cw3-h962':140C 'group':302C 'guard':131C,134C,148C,291C,391C,514C 'h/a':373C 'h962':144C 'har':609C 'head':229C,234C,433C 'henc':367C 'hidden':73B 'high':370C 'higher':385C 'honest':547C 'honor':556C 'ident':250C 'impact':272C,592C 'includ':415C 'inclus':421C,440C,578C 'individu':457C 'inner':199C,210C,454C 'integr':369C 'integrity-high':368C 'intent':224C 'iter':121C 'jackson':2A,25A,29A,33A,37A,41A,46B,55B,403C,426C 'jackson-databind':1A,24A,28A,32A,36A,40A,45B,54B,402C,425C 'java':48B 'jgwh':19A 'json':115C,172C,343C 'jsonanysett':560C 'jsondeseri':539C 'jsontypeinfo':563C 'jsonunwrap':7A,65B,118C,167C,243C,253C,319C,341C,516C,564C 'jsonview':4A,60B,164C,200C,237C,281C,313C,339C,387C,458C,467C 'l':381C 'l/i':380C 'latest':435C 'leak':559C 'line':414C,513C 'loop':585C 'mapperfeature.default':576C 'mass':277C,324C,474C 'mass-assign':276C,323C,473C 'match':154C 'maven':49B 'merg':523C,531C 'method':271C 'mirror':586C 'more-restrict':178C 'n':374C 'n/i':372C 'nest':307C,515C 'non':529C,549C 'non-find':548C 'non-unwrap':528C 'null':244C 'object':205C,308C 'one':512C,588C 'one-lin':511C 'origin':186C 'p9qm':18A 'packag':50B 'parent':382C 'patch/partial-update':526C 'path':261C,496C 'per':197C 'per-field':196C 'poc':327C,472C,484C,593C,603C 'popul':255C 'privileg':89B,279C,303C,453C 'privilegedview.class':165C 'processunwrap':546C,583C 'processunwrappedcreatorproperti':135C,587C 'proof':225C 'prop.deserializeandset':126C 'prop.visibleinview':129C,573C 'properti':9A,67B,72B,119C,123C,155C,160C,223C,239C,251C,270C,311C,317C,495C,584C 'protect':109B 'public':100B,293C 'publicview':246C,351C,459C,478C 'publicview.class':300C 'rcqc':142C 'read':552C 'read-sid':551C 'readerwithview':299C,524C 'receiv':136C,263C 'recurs':521C 'registr':332C 'regular':269C 'regular-properti':268C 'releas':411C 'reli':103B,463C 'replay':64B,112C 'report':482C,486C 'repro':447C 'request':83B,612C 'rest':52B 'rest-api':51B 'restrict':180C 'result':158C 'role':93B,335C,344C 'role/approved/creditbalance':476C 'rout':542C 'runnabl':602C 'runtim':189C,226C,502C 'runtime-confirm':501C 'runtime-verifi':188C 'self':330C 'self-servic':329C 'separate/unsupported':566C 'serial':554C 'servic':331C 'set':88B 'shape':451C 'side':275C,289C,553C 'simultan':481C 'state':304C 'status':95B 'still':79B 'stock':445C 'stock-config':444C 'sub':204C 'sub-object':203C 'summari':110C 'three':354C,595C 'tools.jackson.core':23A,31A,424C 'true':347C,423C 'uncheck':214C 'untrust':321C 'unwrap':202C,221C,518C,520C,530C 'unwrapped-in-unwrap':517C 'unwrappedpropertyhandler.processunwrapped':111C 'use':284C,395C 'variant':500C,596C,608C 'verifi':190C 'view':77B,106B,182C,218C,420C,439C,557C,561C,577C 'whose':309C 'withvaluetoupd':525C 'wors':376C 'write':108B,274C,288C,365C,390C 'write-sid':273C,287C 'written':80B,169C 'x':228C,233C,406C,429C,437C,471C,490C,605C,607C","nicknames":[],"mitigations":[],"who_affected":null,"tier":null,"verified":{},"analyst_revisit_at":null,"first_public_at":"2026-07-14T21:17:06+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-5gvw-p9qm-jgwh","url":"https://github.com/advisories/GHSA-5gvw-p9qm-jgwh","severity":"medium","published_at":"2026-07-21T22:00:43+00:00","modified_at":"2026-10-19T19:31:36+00:00","first_seen_at":"2026-10-23T19:11:32+00:00","fetched_at":"2026-10-23T19:11:32+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-59889","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59889","severity":null,"published_at":"2026-07-14T21:17:06+00:00","modified_at":"2026-10-19T20:19:19+00:00","first_seen_at":"2026-10-23T23:44:52+00:00","fetched_at":"2026-10-23T23:44:52+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}