CWE-407
Allowed-with-ReviewInefficient Algorithmic Complexity
Abstraction: Class · Status: Incomplete
An algorithm in a product has an inefficient worst-case computational complexity that may be detrimental to system performance and can be triggered by an attacker, typically using crafted manipulations that ensure that the worst case is being reached.
262 vulnerabilities reference this CWE, most recent first.
GHSA-M54Q-MM9W-FP6G
Vulnerability from github – Published: 2025-08-29 14:59 – Updated: 2025-08-29 21:04Impact
A denial-of-service was found in Exiv2 version v0.28.5: a quadratic algorithm in the ICC profile parsing code in jpegBase::readMetadata() can cause Exiv2 to run for a long time. Exiv2 is a command-line utility and C++ library for reading, writing, deleting, and modifying the metadata of image files. The denial-of-service is triggered when Exiv2 is used to read the metadata of a crafted jpg image file.
Patches
The bug is fixed in version v0.28.6.
References
Issue: https://github.com/Exiv2/exiv2/issues/3333 Fixes: https://github.com/Exiv2/exiv2/pull/3335 (main branch), https://github.com/Exiv2/exiv2/pull/3345 (0.28.x branch)
For more information
Please see our security policy for information about Exiv2 security.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "Exiv2"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.17.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-55304"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2025-08-29T14:59:37Z",
"nvd_published_at": "2025-08-29T15:15:35Z",
"severity": "LOW"
},
"details": "### Impact\nA denial-of-service was found in Exiv2 version v0.28.5: a quadratic algorithm in the ICC profile parsing code in `jpegBase::readMetadata()` can cause Exiv2 to run for a long time. Exiv2 is a command-line utility and C++ library for reading, writing, deleting, and modifying the metadata of image files. The denial-of-service is triggered when Exiv2 is used to read the metadata of a crafted jpg image file.\n\n### Patches\nThe bug is fixed in version v0.28.6.\n\n### References\nIssue: https://github.com/Exiv2/exiv2/issues/3333\nFixes: https://github.com/Exiv2/exiv2/pull/3335 (main branch), https://github.com/Exiv2/exiv2/pull/3345 (0.28.x branch)\n\n### For more information\nPlease see our [security policy](https://github.com/Exiv2/exiv2/security/policy) for information about Exiv2 security.",
"id": "GHSA-m54q-mm9w-fp6g",
"modified": "2025-08-29T21:04:02Z",
"published": "2025-08-29T14:59:37Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Exiv2/exiv2/security/advisories/GHSA-m54q-mm9w-fp6g"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-55304"
},
{
"type": "WEB",
"url": "https://github.com/Exiv2/exiv2/issues/3333"
},
{
"type": "WEB",
"url": "https://github.com/Exiv2/exiv2/pull/3335"
},
{
"type": "WEB",
"url": "https://github.com/Exiv2/exiv2/pull/3345"
},
{
"type": "PACKAGE",
"url": "https://github.com/Exiv2/exiv2"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:A/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Exiv2 has quadratic performance in ICC profile parsing in JpegBase::readMetadata"
}
GHSA-M6HH-VP2V-RM5M
Vulnerability from github – Published: 2025-02-20 03:32 – Updated: 2025-02-20 03:32The hash table used to manage connections in picoquic before b80fd3f uses a weak hash function, allowing remote attackers to cause a considerable CPU load on the server (a Hash DoS attack) by initiating connections with colliding Source Connection IDs (SCIDs).
{
"affected": [],
"aliases": [
"CVE-2025-24946"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-02-20T03:15:12Z",
"severity": "MODERATE"
},
"details": "The hash table used to manage connections in picoquic before b80fd3f uses a weak hash function, allowing remote attackers to cause a considerable CPU load on the server (a Hash DoS attack) by initiating connections with colliding Source Connection IDs (SCIDs).",
"id": "GHSA-m6hh-vp2v-rm5m",
"modified": "2025-02-20T03:32:03Z",
"published": "2025-02-20T03:32:03Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-24946"
},
{
"type": "WEB",
"url": "https://github.com/private-octopus/picoquic/commit/b80fd3f5903279ae3e7714ee4109363d9ab4491a"
},
{
"type": "WEB",
"url": "https://github.com/ncc-pbottine/QUIC-Hash-Dos-Advisory"
}
],
"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"
}
]
}
GHSA-MFJ6-6P54-M98C
Vulnerability from github – Published: 2026-03-31 23:49 – Updated: 2026-03-31 23:49Impact
The GraphQL query complexity validator can be exploited to cause a denial-of-service by sending a crafted query with binary fan-out fragment spreads. A single unauthenticated request can block the Node.js event loop for seconds, denying service to all concurrent users. This only affects deployments that have enabled the requestComplexity.graphQLDepth or requestComplexity.graphQLFields configuration options.
Patches
The fix replaces the per-branch fragment traversal with memoized fragment computation, reducing the traversal from exponential O(2^N) to linear O(N) time. Additionally, early termination aborts the traversal as soon as configured limits are exceeded.
Workarounds
Disable GraphQL complexity limits by setting requestComplexity.graphQLDepth and requestComplexity.graphQLFields to -1 (the default).
Resources
- GitHub security advisory: https://github.com/parse-community/parse-server/security/advisories/GHSA-mfj6-6p54-m98c
- Fix Parse Server 9: https://github.com/parse-community/parse-server/pull/10344
- Fix Parse Server 8: https://github.com/parse-community/parse-server/pull/10345
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "parse-server"
},
"ranges": [
{
"events": [
{
"introduced": "9.0.0"
},
{
"fixed": "9.7.0-alpha.12"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "parse-server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "8.6.68"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-34573"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-31T23:49:18Z",
"nvd_published_at": "2026-03-31T16:16:33Z",
"severity": "HIGH"
},
"details": "### Impact\n\nThe GraphQL query complexity validator can be exploited to cause a denial-of-service by sending a crafted query with binary fan-out fragment spreads. A single unauthenticated request can block the Node.js event loop for seconds, denying service to all concurrent users. This only affects deployments that have enabled the `requestComplexity.graphQLDepth` or `requestComplexity.graphQLFields` configuration options.\n\n### Patches\n\nThe fix replaces the per-branch fragment traversal with memoized fragment computation, reducing the traversal from exponential O(2^N) to linear O(N) time. Additionally, early termination aborts the traversal as soon as configured limits are exceeded.\n\n### Workarounds\n\nDisable GraphQL complexity limits by setting `requestComplexity.graphQLDepth` and `requestComplexity.graphQLFields` to `-1` (the default).\n\n### Resources\n\n- GitHub security advisory: https://github.com/parse-community/parse-server/security/advisories/GHSA-mfj6-6p54-m98c\n- Fix Parse Server 9: https://github.com/parse-community/parse-server/pull/10344\n- Fix Parse Server 8: https://github.com/parse-community/parse-server/pull/10345",
"id": "GHSA-mfj6-6p54-m98c",
"modified": "2026-03-31T23:49:18Z",
"published": "2026-03-31T23:49:18Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/security/advisories/GHSA-mfj6-6p54-m98c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34573"
},
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/pull/10344"
},
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/pull/10345"
},
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/commit/ea15412795f34594cc8a674fe858d445675e0295"
},
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/commit/f759bda075298ec44e2b4fb57659a0c56620483b"
},
{
"type": "PACKAGE",
"url": "https://github.com/parse-community/parse-server"
}
],
"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:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "parse-server has GraphQL complexity validator exponential fragment traversal DoS"
}
GHSA-MH25-X5HQ-WRQP
Vulnerability from github – Published: 2026-08-06 20:41 – Updated: 2026-08-06 20:41Impact
UniqueSlugNormalizer::normalize() makes each slug document-unique by searching for an unused numeric suffix, but restarts that search from 1 on every collision. The k-th heading that collapses to the same base slug performs k−1 array lookups, so K colliding slugs cost Σ(k−1) = O(K²). An attacker can force every heading onto a single base slug trivially — many empty ATX headings, identical heading text, or punctuation-only headings that normalize to the empty string.
The path is reached whenever the shared slug normalizer runs over attacker-controlled text. That happens when HeadingPermalinkExtension is registered (its HeadingPermalinkProcessor normalizes every heading), independently through FootnoteExtension (its AnonymousFootnoteRefParser normalizes every ^[label] reference), and on any TableOfContentsExtension site (which requires HeadingPermalinkExtension to be co-registered). The default slug_normalizer/unique setting (UniqueSlugNormalizerInterface::PER_DOCUMENT) accumulates collisions across the whole document. No authentication is required — a small document body turns into seconds of CPU and denies service. Availability impact only. UniqueSlugNormalizer was introduced in 2.0.0 (first shipped in 2.0.0-beta1, May 2021); the 1.x heading-permalink slug generator performed no de-duplication and is not affected. All 2.x releases (including 2.8.x) are affected.
Workarounds
Integrators who cannot upgrade immediately can:
- Set
slug_normalizer/uniquetofalse/UniqueSlugNormalizerInterface::DISABLED, which stops the de-duplication scan entirely — at the cost of losing id uniqueness (colliding headings then share an anchor). - Disable
HeadingPermalinkExtension(andTableOfContentsExtension, which depends on it), andFootnoteExtensionwhere anonymous footnotes reach the same normalizer, for untrusted Markdown. - Cap the accepted document size / heading count upstream so K cannot reach the quadratic danger zone.
Each of these trades off functionality or correctness; upgrading to the patched release (which removes the quadratic behavior while keeping unique ids and identical output) is the recommended remediation.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "league/commonmark"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "2.9.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-06T20:41:45Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Impact\n\n`UniqueSlugNormalizer::normalize()` makes each slug document-unique by searching for an unused numeric suffix, but **restarts that search from `1` on every collision**. The k-th heading that collapses to the same base slug performs k\u22121 array lookups, so K colliding slugs cost \u03a3(k\u22121) = **O(K\u00b2)**. An attacker can force every heading onto a single base slug trivially \u2014 many empty ATX headings, identical heading text, or punctuation-only headings that normalize to the empty string.\n\nThe path is reached whenever the shared slug normalizer runs over attacker-controlled text. That happens when `HeadingPermalinkExtension` is registered (its `HeadingPermalinkProcessor` normalizes every heading), independently through `FootnoteExtension` (its `AnonymousFootnoteRefParser` normalizes every `^[label]` reference), and on any `TableOfContentsExtension` site (which requires `HeadingPermalinkExtension` to be co-registered). The default `slug_normalizer/unique` setting (`UniqueSlugNormalizerInterface::PER_DOCUMENT`) accumulates collisions across the whole document. No authentication is required \u2014 a small document body turns into seconds of CPU and denies service. Availability impact only. **`UniqueSlugNormalizer` was introduced in 2.0.0 (first shipped in 2.0.0-beta1, May 2021); the 1.x heading-permalink slug generator performed no de-duplication and is not affected. All 2.x releases (including 2.8.x) are affected.**\n\n### Workarounds\n\nIntegrators who cannot upgrade immediately can:\n\n- **Set `slug_normalizer/unique` to `false` / `UniqueSlugNormalizerInterface::DISABLED`**, which stops the de-duplication scan entirely \u2014 at the cost of losing id uniqueness (colliding headings then share an anchor).\n- **Disable `HeadingPermalinkExtension`** (and `TableOfContentsExtension`, which depends on it), and `FootnoteExtension` where anonymous footnotes reach the same normalizer, for untrusted Markdown.\n- **Cap the accepted document size / heading count upstream** so K cannot reach the quadratic danger zone.\n\nEach of these trades off functionality or correctness; upgrading to the patched release (which removes the quadratic behavior while keeping unique ids and identical output) is the recommended remediation.",
"id": "GHSA-mh25-x5hq-wrqp",
"modified": "2026-08-06T20:41:45Z",
"published": "2026-08-06T20:41:45Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/thephpleague/commonmark/security/advisories/GHSA-mh25-x5hq-wrqp"
},
{
"type": "PACKAGE",
"url": "https://github.com/thephpleague/commonmark"
},
{
"type": "WEB",
"url": "https://github.com/thephpleague/commonmark/releases/tag/2.9.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": "league/commonmark: Denial of service via colliding heading slugs"
}
GHSA-MVMF-94V6-879G
Vulnerability from github – Published: 2026-06-30 15:30 – Updated: 2026-07-02 21:32fzf is vulnerable to a Denial of Service (DoS) due to inefficient HTTP body processing in the --listen mode due to inefficient HTTP body processing using repeated string concatenation, resulting in quadratic time complexity (O(n²)). A crafted POST request with many small segments can trigger excessive CPU usage during request handling.This allows a single malicious request to monopolize the single‑threaded HTTP server, blocking all other clients and resulting in denial of service.
This issue was fixed in version 0.73.1.
{
"affected": [],
"aliases": [
"CVE-2026-53433"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-30T13:19:13Z",
"severity": "MODERATE"
},
"details": "fzf is vulnerable to a Denial of Service (DoS) due to inefficient HTTP body processing in the --listen mode due to inefficient HTTP body processing using repeated string concatenation, resulting in quadratic time complexity (O(n\u00b2)). A crafted POST request with many small segments can trigger excessive CPU usage during request handling.This allows a single malicious request to monopolize the single\u2011threaded HTTP server, blocking all other clients and resulting in denial of service.\n\nThis issue was fixed in version 0.73.1.",
"id": "GHSA-mvmf-94v6-879g",
"modified": "2026-07-02T21:32:10Z",
"published": "2026-06-30T15:30:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53433"
},
{
"type": "WEB",
"url": "https://github.com/junegunn/fzf/commit/7963a2c6586c0b9eaa89b8995de8f0e08cf8a4ce"
},
{
"type": "WEB",
"url": "https://cert.pl/en/posts/2026/06/CVE-2026-53432"
},
{
"type": "WEB",
"url": "https://github.com/junegunn/fzf"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-PM4M-PH32-GHV5
Vulnerability from github – Published: 2026-07-24 16:47 – Updated: 2026-08-13 17:47Summary
Parsing a small YAML document can take exponential time. An application that calls load() or loadAll() on untrusted input can be hung by a payload under 200 bytes.
Details
When an entry in a flow sequence turns out to be a key: value pair, the parser rewinds and parses that entry a second time as the key.
If the key is itself a nested flow sequence of the same shape, every level is parsed twice, so the total work is O(2^n) in the nesting depth. The default maxDepth of 100 does not help, because the time is already unmanageable at about 30 to 40 levels.
Root cause, potentially the: readFlowCollection in parser.ts, the restoreState followed by a second parseNode further down.
PoC
const yaml = require('js-yaml')
const n = 30
yaml.load('[ '.repeat(n) + '1' + ' ]: 0'.repeat(n))
With default options: 22 levels takes about 1 second, 26 levels about 17 seconds, 30 levels over 2 minutes. The input stays under 200 bytes and grows linearly with n.
Impact
Denial of service. A single small request can keep one CPU busy for minutes or longer and blocks the Node event loop, so one request can stall the whole process. No anchors, aliases, merges, tags, or non default options are required, and it reproduces on the default schema.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.2.1"
},
"package": {
"ecosystem": "npm",
"name": "js-yaml"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0"
},
{
"fixed": "5.2.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-73643"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-24T16:47:36Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\nParsing a small YAML document can take exponential time. An application that calls `load()` or `loadAll()` on untrusted input can be hung by a payload under 200 bytes.\n\n### Details\nWhen an entry in a flow sequence turns out to be a `key: value` pair, the parser rewinds and parses that entry a second time as the key.\nIf the key is itself a nested flow sequence of the same shape, every level is parsed twice, so the total work is O(2^n) in the nesting depth. The default `maxDepth` of 100 does not help, because the time is already unmanageable at about 30 to 40 levels.\n\nRoot cause, potentially the: `readFlowCollection` in [parser.ts](https://github.com/nodeca/js-yaml/blob/master/src/parser/parser.ts), the `restoreState` followed by a second `parseNode` further down.\n\n\n### PoC\n\n```javascript\nconst yaml = require(\u0027js-yaml\u0027)\nconst n = 30\nyaml.load(\u0027[ \u0027.repeat(n) + \u00271\u0027 + \u0027 ]: 0\u0027.repeat(n))\n```\n\nWith default options: 22 levels takes about 1 second, 26 levels about 17 seconds, 30 levels over 2 minutes. The input stays under 200 bytes and grows linearly with `n`.\n\n### Impact\nDenial of service. A single small request can keep one CPU busy for minutes or longer and blocks the Node event loop, so one request can stall the whole process. No anchors, aliases, merges, tags, or non default options are required, and it reproduces on the default schema.",
"id": "GHSA-pm4m-ph32-ghv5",
"modified": "2026-08-13T17:47:36Z",
"published": "2026-07-24T16:47:36Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nodeca/js-yaml/security/advisories/GHSA-pm4m-ph32-ghv5"
},
{
"type": "WEB",
"url": "https://github.com/nodeca/js-yaml/commit/3e5240f9cbe645ce5afb58524954a13c8539c853"
},
{
"type": "PACKAGE",
"url": "https://github.com/nodeca/js-yaml"
},
{
"type": "WEB",
"url": "https://github.com/nodeca/js-yaml/releases/tag/5.2.2"
}
],
"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": "js-yaml: Exponential parsing time in flow collections leads to denial of service"
}
GHSA-PM8W-JQ9R-X5RP
Vulnerability from github – Published: 2026-02-09 15:30 – Updated: 2026-06-30 00:31A flaw was found in GnuTLS. This vulnerability allows a denial of service (DoS) by excessive CPU (Central Processing Unit) and memory consumption via specially crafted malicious certificates containing a large number of name constraints and subject alternative names (SANs).
{
"affected": [],
"aliases": [
"CVE-2025-14831"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-02-09T15:16:09Z",
"severity": "MODERATE"
},
"details": "A flaw was found in GnuTLS. This vulnerability allows a denial of service (DoS) by excessive CPU (Central Processing Unit) and memory consumption via specially crafted malicious certificates containing a large number of name constraints and subject alternative names (SANs).",
"id": "GHSA-pm8w-jq9r-x5rp",
"modified": "2026-06-30T00:31:28Z",
"published": "2026-02-09T15:30:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-14831"
},
{
"type": "WEB",
"url": "https://gitlab.com/gnutls/gnutls/-/issues/1773"
},
{
"type": "WEB",
"url": "https://cert-portal.siemens.com/productcert/html/ssa-032379.html"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2423177"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2025-14831"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:8748"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:8747"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:8746"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:7477"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:7335"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:7329"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:6738"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:6737"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:6630"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:6618"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:5606"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:5585"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:4943"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:4655"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:4188"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:3477"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:33125"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:30850"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:30849"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:25096"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:16174"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:16009"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:16008"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:13812"
}
],
"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"
}
]
}
GHSA-PW35-6253-9877
Vulnerability from github – Published: 2026-08-13 21:36 – Updated: 2026-08-13 21:36Inefficient Algorithmic Complexity (CWE-407) in Kibana can lead to denial of service via Input Data Manipulation (CAPEC-153). A specially crafted, deeply nested expression submitted to a Kibana TSVB visualization is evaluated with a worst-case cost that grows disproportionately with the size of the input. Because the evaluation runs synchronously, a single request consumes the Kibana request-processing thread indefinitely, and Kibana stops responding to all further requests until the service is restarted.
{
"affected": [],
"aliases": [
"CVE-2026-72663"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-13T20:17:26Z",
"severity": "MODERATE"
},
"details": "Inefficient Algorithmic Complexity (CWE-407) in Kibana can lead to denial of service via Input Data Manipulation (CAPEC-153). A specially crafted, deeply nested expression submitted to a Kibana TSVB visualization is evaluated with a worst-case cost that grows disproportionately with the size of the input. Because the evaluation runs synchronously, a single request consumes the Kibana request-processing thread indefinitely, and Kibana stops responding to all further requests until the service is restarted.",
"id": "GHSA-pw35-6253-9877",
"modified": "2026-08-13T21:36:09Z",
"published": "2026-08-13T21:36:09Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72663"
},
{
"type": "WEB",
"url": "https://discuss.elastic.co/t/kibana-8-19-20-and-9-4-5-security-update-esa-2026-104/389520"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-PWGV-4X5Q-6M9F
Vulnerability from github – Published: 2026-08-17 17:49 – Updated: 2026-08-17 17:49Summary
sqlparse ships hard limits (MAX_GROUPING_DEPTH=100, MAX_GROUPING_TOKENS=10000) intended to bound parsing work on attacker-supplied SQL, but the path that reaches those limits is itself O(n*depth) per token-group construction. A ~1-2 KB SQL payload (e.g. SELECT (((((1))))) ... with 500-2000 nesting levels, or a 200-400-level nested CASE WHEN chain) drives the parser to spend multiple seconds of CPU before the depth cap raises SQLParseError. Concretely: a 2 KB malicious payload consumes ~10 seconds of CPU per request on a single worker (~5000x CPU-to-input amplification), while a benign 1 KB SQL completes in ~3 ms.
The root cause is TokenList.__init__ calling super().__init__(None, str(self)). TokenList.__str__ flattens the entire subtree on every call, and grouping constructs a new TokenList for every parenthesis / CASE / list group, so a tree of depth d with n total tokens performs O(n*d) flatten work just to materialize the cached value field, which is then never read for grouped nodes (they override __str__).
This is a distinct quadratic from the input-size caps added in GHSA-2m57-hf25-phgg / GHSA-27jp-wm6q-gp25: those caps prevent unbounded work, but the time required to trigger the caps is itself superlinear in payload size.
Affected components
sqlparse 0.5.5 (latest) and every prior version that ships TokenList.__init__. The offending line has existed since the introduction of the cached-value invariant; the recent DoS-protection commit (da67ac1, 2025-12-08) added depth + token caps to _group_matching / _group but left the per-node str(self) materialization untouched.
Vulnerable code (file:line)
sqlparse/sql.py#L162 (release 0.5.5) / sqlparse/sql.py#L167 (current master):
class TokenList(Token):
__slots__ = 'tokens'
def __init__(self, tokens=None):
self.tokens = tokens or []
[setattr(token, 'parent', self) for token in self.tokens]
super().__init__(None, str(self)) # ← O(subtree) work per group
self.is_group = True
def __str__(self):
return ''.join(token.value for token in self.flatten())
__str__ recurses via flatten() over the entire subtree below self. Every TokenList constructed during grouping (every Parenthesis, Case, IdentifierList, etc.) runs this on its current children, which themselves recursively call flatten(). For grouping that builds a tree of depth d containing n tokens, the construction cost is O(n * d).
The grouping pipeline that triggers it lives at sqlparse/engine/grouping.py#L80 (group_parenthesis) and sqlparse/engine/grouping.py#L84 (group_case). Both call _group_matching which builds nested Parenthesis / Case TokenList instances bottom-up.
Reachable / How input reaches the sink
sqlparse.parse(sql), sqlparse.format(sql, reindent=True), and sqlparse.split(sql) are the documented entry points and all flow into engine/filter_stack.py:run → engine/grouping.py:group → group_parenthesis / group_case. There is no opt-in flag: the quadratic runs on default configuration whenever attacker-controlled SQL contains nested parentheses, nested CASE WHEN, nested subqueries, or nested ARRAY[] literals.
Real-world consumers that feed user input directly into these entry points include any SQL formatter web service (the sqlformat.org-style class of tools), Django's format_debug_sql (django/db/backends/base/operations.py) used when a debug toolbar shows user-typed SQL, and downstream metadata libraries such as sql-metadata (Parser(sql).columns triggers the same O(n*d) path and reproduces the multi-second hang on the same inputs).
Proof of concept
Minimal in-process reproduction (sqlparse 0.5.5, default settings, no caps overridden):
import sqlparse, time, signal
def _h(s, f): raise TimeoutError()
signal.signal(signal.SIGALRM, _h)
def measure(label, sql, fn):
signal.alarm(30)
t0 = time.perf_counter()
status = 'OK'
try:
fn(sql)
except sqlparse.exceptions.SQLParseError:
status = 'CAP'
except TimeoutError:
status = 'TIMEOUT'
finally:
signal.alarm(0)
dt = (time.perf_counter() - t0) * 1000
print(f' {status:8} {dt:8.1f}ms {label} ({len(sql)} B)')
# Vector 1: deeply nested parentheses
for n in (200, 500, 1000, 2000):
sql = 'SELECT ' + '(' * n + '1' + ')' * n
measure(f'nested-paren n={n}', sql, sqlparse.parse)
# Vector 2: deeply nested CASE WHEN
for n in (100, 200, 400):
case = '1'
for i in range(n):
case = f'CASE WHEN x={i} THEN {case} ELSE NULL END'
measure(f'CASE-nested n={n}', f'SELECT {case} FROM t', sqlparse.parse)
Output on the reporter's machine (Python 3.9, sqlparse 0.5.5, single core):
CAP 80.7ms nested-paren n=200 (408 B)
CAP 1342.9ms nested-paren n=500 (1008 B)
CAP 11206.9ms nested-paren n=1000 (2008 B)
TIMEOUT >10000ms nested-paren n=2000 (4008 B)
CAP 83.1ms CASE-nested n=100 (3405 B)
CAP 559.6ms CASE-nested n=200 (6905 B)
CAP 5012.2ms CASE-nested n=400 (13905 B)
cProfile attribution (nested-paren n=500, 1008 B input, 3.1 s total):
ncalls cumtime filename:lineno(function)
501 3.133 sqlparse/sql.py:165(__str__)
501 3.127 {method 'join' of 'str' objects}
252504 3.110 sqlparse/sql.py:166(<genexpr>)
42168504 3.079 sqlparse/sql.py:207(flatten)
42 million flatten() calls for a 1 KB input. The cap raises at depth 100, but TokenList.__init__ ran str(self) once per group construction and each call walked the partial subtree.
End-to-end reproduction (against running consumer)
victim_app.py (a 50-line Flask formatter, the canonical sqlparse consumer pattern):
from flask import Flask, request, jsonify
import sqlparse, time
app = Flask(__name__)
@app.route('/parse', methods=['POST'])
def parse_sql():
sql = request.get_data(as_text=True)
t0 = time.perf_counter()
try:
sqlparse.parse(sql)
return jsonify({'ok': True, 'parse_ms': round((time.perf_counter()-t0)*1000, 1)})
except sqlparse.exceptions.SQLParseError as e:
return jsonify({'ok': False, 'parse_ms': round((time.perf_counter()-t0)*1000, 1), 'error': str(e)}), 400
@app.route('/format', methods=['POST'])
def format_sql():
sql = request.get_data(as_text=True)
t0 = time.perf_counter()
formatted = sqlparse.format(sql, reindent=True, keyword_case='upper')
return jsonify({'ok': True, 'parse_ms': round((time.perf_counter()-t0)*1000, 1), 'len': len(formatted)})
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5099, threaded=False)
Driver run (Python 3.9, sqlparse 0.5.5, threaded=False so one worker per request):
=== Baseline (benign payloads) ===
benign small SQL 8B wire= 8.8ms server= 0.2ms
benign 1 KB SQL 220B wire= 4.1ms server= 2.5ms
benign flat 500-cols 2902B wire= 91.7ms server= 90.2ms
=== Malicious payloads (within default caps) ===
nested-paren n=200 408B wire= 84.0ms server= 82.6ms ok=False
nested-paren n=500 1008B wire= 1371.9ms server= 1370.5ms ok=False
nested-paren n=1000 2008B wire=10335.3ms server=10333.7ms ok=False
nested-paren n=2000 4008B wire=10661.4ms server=10659.6ms ok=False
CASE-nested n=400 13905B wire= 5136.4ms server= 5134.7ms ok=False
IN-tuple-format n=1000 9922B wire= 3852.8ms server= 3851.2ms ok=True
A 2 KB payload (nested-paren n=1000) pins one worker for 10 seconds at 100% CPU. With gunicorn -w N deploying the same app, N concurrent malicious requests exhaust every worker and bring the service down. The cap SQLParseError exception is delivered to the caller, but only after the CPU work is already burnt.
Impact
- Single-threaded service: 1-2 KB payload locks the worker for 1-10 seconds (CWE-1333 / CWE-405 / CWE-400 — uncontrolled resource consumption).
- Multi-worker service: attacker sends
Nparallel requests, exhausts the worker pool. - Wire-to-CPU amplification on the worst vector: ~5000x (2 KB request → 10 seconds CPU).
- Downstream library impact:
sql-metadata.Parser(sql).columnscallssqlparse.parseinternally and inherits the exact same hang (nested-paren n=1000→ 11.3 s).
Suggested fix
Replace the eager str(self) materialization with a single-pass concatenation of children's already-cached value fields. The Token.value invariant value == str(self) at construction is preserved (children's value is itself built the same way bottom-up), but the per-node cost drops from O(subtree) to O(len(self.tokens)):
def __init__(self, tokens=None):
self.tokens = tokens or []
[setattr(token, 'parent', self) for token in self.tokens]
# Avoid materializing the full subtree via str(self): concatenating
# children's already-cached `value` is O(len(tokens)) per group,
# whereas str(self) recursively flattens the entire subtree which is
# O(subtree) per node and turns nested grouping into O(n * depth).
super().__init__(None, ''.join(token.value for token in self.tokens))
self.is_group = True
Measured against the 0.5.5 source tree with the patch applied locally and the full existing test-suite running (479 passed, 2 xfailed, 1 xpassed; the same baseline as unpatched 0d24023):
| Vector | Before fix | After fix | Speedup |
|---|---|---|---|
| nested-paren n=500 | 1336 ms | 11 ms | 121x |
| nested-paren n=1000 | 11206 ms | 22 ms | 509x |
| nested-paren n=2000 | TIMEOUT (>10 s) | 45 ms | 220x+ |
| CASE-nested n=200 | 559 ms | 25 ms | 22x |
| CASE-nested n=500 | TIMEOUT (>10 s) | 61 ms | 160x+ |
| benign 1 KB SQL | 3 ms | 3 ms | unchanged |
End-to-end Flask victim_app re-run against the patched library:
nested-paren n=1000 2008B server= 34.6ms
nested-paren n=2000 4008B server= 67.2ms
CASE-nested n=400 13905B server= 49.5ms
benign 1 KB SQL 220B server= 3.4ms
The IN-tuple format() vector observed at n=1000 (3.8 s for ~10 KB input) is a separate quadratic in the reindent filter (filters/reindent.py:_get_offset → _flatten_up_to_token) and is not covered by this advisory; please consider it as a follow-up if the maintainer would like a separate report.
Fix PR
A fix PR against the temp private fork, mirroring the diff above with a regression test (test_nested_paren_within_cap_under_50ms), is attached and linked from this advisory.
Credit
Reported by tonghuaroot.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.5.5"
},
"package": {
"ecosystem": "PyPI",
"name": "sqlparse"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.6.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54284"
],
"database_specific": {
"cwe_ids": [
"CWE-1333",
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-17T17:49:47Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\n\n`sqlparse` ships hard limits (`MAX_GROUPING_DEPTH=100`, `MAX_GROUPING_TOKENS=10000`) intended to bound parsing work on attacker-supplied SQL, but the path that *reaches* those limits is itself `O(n*depth)` per token-group construction. A ~1-2 KB SQL payload (e.g. `SELECT (((((1))))) ...` with 500-2000 nesting levels, or a 200-400-level nested `CASE WHEN` chain) drives the parser to spend multiple seconds of CPU before the depth cap raises `SQLParseError`. Concretely: a 2 KB malicious payload consumes ~10 seconds of CPU per request on a single worker (~5000x CPU-to-input amplification), while a benign 1 KB SQL completes in ~3 ms.\n\nThe root cause is `TokenList.__init__` calling `super().__init__(None, str(self))`. `TokenList.__str__` flattens the entire subtree on every call, and grouping constructs a new `TokenList` for every parenthesis / CASE / list group, so a tree of depth `d` with `n` total tokens performs `O(n*d)` flatten work just to materialize the cached `value` field, which is then never read for grouped nodes (they override `__str__`).\n\nThis is a distinct quadratic from the input-size caps added in GHSA-2m57-hf25-phgg / GHSA-27jp-wm6q-gp25: those caps prevent unbounded work, but the time required to *trigger* the caps is itself superlinear in payload size.\n\n### Affected components\n\n`sqlparse` 0.5.5 (latest) and every prior version that ships `TokenList.__init__`. The offending line has existed since the introduction of the cached-value invariant; the recent DoS-protection commit (`da67ac1`, 2025-12-08) added depth + token caps to `_group_matching` / `_group` but left the per-node `str(self)` materialization untouched.\n\n### Vulnerable code (file:line)\n\n[`sqlparse/sql.py#L162`](https://github.com/andialbrecht/sqlparse/blob/0.5.5/sqlparse/sql.py#L162) (release 0.5.5) / [`sqlparse/sql.py#L167`](https://github.com/andialbrecht/sqlparse/blob/c923da9c5a8e8403dd32efc2171b60a177444d43/sqlparse/sql.py#L167) (current `master`):\n\n```python\nclass TokenList(Token):\n __slots__ = \u0027tokens\u0027\n\n def __init__(self, tokens=None):\n self.tokens = tokens or []\n [setattr(token, \u0027parent\u0027, self) for token in self.tokens]\n super().__init__(None, str(self)) # \u2190 O(subtree) work per group\n self.is_group = True\n\n def __str__(self):\n return \u0027\u0027.join(token.value for token in self.flatten())\n```\n\n`__str__` recurses via `flatten()` over the *entire* subtree below `self`. Every `TokenList` constructed during grouping (every `Parenthesis`, `Case`, `IdentifierList`, etc.) runs this on its current children, which themselves recursively call `flatten()`. For grouping that builds a tree of depth `d` containing `n` tokens, the construction cost is `O(n * d)`.\n\nThe grouping pipeline that triggers it lives at [`sqlparse/engine/grouping.py#L80`](https://github.com/andialbrecht/sqlparse/blob/0.5.5/sqlparse/engine/grouping.py#L80) (`group_parenthesis`) and [`sqlparse/engine/grouping.py#L84`](https://github.com/andialbrecht/sqlparse/blob/0.5.5/sqlparse/engine/grouping.py#L84) (`group_case`). Both call `_group_matching` which builds nested `Parenthesis` / `Case` `TokenList` instances bottom-up.\n\n### Reachable / How input reaches the sink\n\n`sqlparse.parse(sql)`, `sqlparse.format(sql, reindent=True)`, and `sqlparse.split(sql)` are the documented entry points and all flow into `engine/filter_stack.py:run` \u2192 `engine/grouping.py:group` \u2192 `group_parenthesis` / `group_case`. There is no opt-in flag: the quadratic runs on default configuration whenever attacker-controlled SQL contains nested parentheses, nested `CASE WHEN`, nested subqueries, or nested `ARRAY[]` literals.\n\nReal-world consumers that feed user input directly into these entry points include any SQL formatter web service (the `sqlformat.org`-style class of tools), Django\u0027s `format_debug_sql` (`django/db/backends/base/operations.py`) used when a debug toolbar shows user-typed SQL, and downstream metadata libraries such as `sql-metadata` (`Parser(sql).columns` triggers the same O(n*d) path and reproduces the multi-second hang on the same inputs).\n\n### Proof of concept\n\nMinimal in-process reproduction (sqlparse 0.5.5, default settings, no caps overridden):\n\n```python\nimport sqlparse, time, signal\n\ndef _h(s, f): raise TimeoutError()\nsignal.signal(signal.SIGALRM, _h)\n\ndef measure(label, sql, fn):\n signal.alarm(30)\n t0 = time.perf_counter()\n status = \u0027OK\u0027\n try:\n fn(sql)\n except sqlparse.exceptions.SQLParseError:\n status = \u0027CAP\u0027\n except TimeoutError:\n status = \u0027TIMEOUT\u0027\n finally:\n signal.alarm(0)\n dt = (time.perf_counter() - t0) * 1000\n print(f\u0027 {status:8} {dt:8.1f}ms {label} ({len(sql)} B)\u0027)\n\n# Vector 1: deeply nested parentheses\nfor n in (200, 500, 1000, 2000):\n sql = \u0027SELECT \u0027 + \u0027(\u0027 * n + \u00271\u0027 + \u0027)\u0027 * n\n measure(f\u0027nested-paren n={n}\u0027, sql, sqlparse.parse)\n\n# Vector 2: deeply nested CASE WHEN\nfor n in (100, 200, 400):\n case = \u00271\u0027\n for i in range(n):\n case = f\u0027CASE WHEN x={i} THEN {case} ELSE NULL END\u0027\n measure(f\u0027CASE-nested n={n}\u0027, f\u0027SELECT {case} FROM t\u0027, sqlparse.parse)\n```\n\nOutput on the reporter\u0027s machine (Python 3.9, sqlparse 0.5.5, single core):\n\n```\n CAP 80.7ms nested-paren n=200 (408 B)\n CAP 1342.9ms nested-paren n=500 (1008 B)\n CAP 11206.9ms nested-paren n=1000 (2008 B)\n TIMEOUT \u003e10000ms nested-paren n=2000 (4008 B)\n CAP 83.1ms CASE-nested n=100 (3405 B)\n CAP 559.6ms CASE-nested n=200 (6905 B)\n CAP 5012.2ms CASE-nested n=400 (13905 B)\n```\n\n`cProfile` attribution (nested-paren n=500, 1008 B input, 3.1 s total):\n\n```\nncalls cumtime filename:lineno(function)\n 501 3.133 sqlparse/sql.py:165(__str__)\n 501 3.127 {method \u0027join\u0027 of \u0027str\u0027 objects}\n252504 3.110 sqlparse/sql.py:166(\u003cgenexpr\u003e)\n42168504 3.079 sqlparse/sql.py:207(flatten)\n```\n\n42 million `flatten()` calls for a 1 KB input. The cap raises at depth 100, but `TokenList.__init__` ran `str(self)` once per group construction and each call walked the partial subtree.\n\n### End-to-end reproduction (against running consumer)\n\n`victim_app.py` (a 50-line Flask formatter, the canonical sqlparse consumer pattern):\n\n```python\nfrom flask import Flask, request, jsonify\nimport sqlparse, time\napp = Flask(__name__)\n\n@app.route(\u0027/parse\u0027, methods=[\u0027POST\u0027])\ndef parse_sql():\n sql = request.get_data(as_text=True)\n t0 = time.perf_counter()\n try:\n sqlparse.parse(sql)\n return jsonify({\u0027ok\u0027: True, \u0027parse_ms\u0027: round((time.perf_counter()-t0)*1000, 1)})\n except sqlparse.exceptions.SQLParseError as e:\n return jsonify({\u0027ok\u0027: False, \u0027parse_ms\u0027: round((time.perf_counter()-t0)*1000, 1), \u0027error\u0027: str(e)}), 400\n\n@app.route(\u0027/format\u0027, methods=[\u0027POST\u0027])\ndef format_sql():\n sql = request.get_data(as_text=True)\n t0 = time.perf_counter()\n formatted = sqlparse.format(sql, reindent=True, keyword_case=\u0027upper\u0027)\n return jsonify({\u0027ok\u0027: True, \u0027parse_ms\u0027: round((time.perf_counter()-t0)*1000, 1), \u0027len\u0027: len(formatted)})\n\nif __name__ == \u0027__main__\u0027:\n app.run(host=\u0027127.0.0.1\u0027, port=5099, threaded=False)\n```\n\nDriver run (Python 3.9, sqlparse 0.5.5, `threaded=False` so one worker per request):\n\n```\n=== Baseline (benign payloads) ===\n benign small SQL 8B wire= 8.8ms server= 0.2ms\n benign 1 KB SQL 220B wire= 4.1ms server= 2.5ms\n benign flat 500-cols 2902B wire= 91.7ms server= 90.2ms\n\n=== Malicious payloads (within default caps) ===\n nested-paren n=200 408B wire= 84.0ms server= 82.6ms ok=False\n nested-paren n=500 1008B wire= 1371.9ms server= 1370.5ms ok=False\n nested-paren n=1000 2008B wire=10335.3ms server=10333.7ms ok=False\n nested-paren n=2000 4008B wire=10661.4ms server=10659.6ms ok=False\n CASE-nested n=400 13905B wire= 5136.4ms server= 5134.7ms ok=False\n IN-tuple-format n=1000 9922B wire= 3852.8ms server= 3851.2ms ok=True\n```\n\nA 2 KB payload (`nested-paren n=1000`) pins one worker for 10 seconds at 100% CPU. With `gunicorn -w N` deploying the same app, `N` concurrent malicious requests exhaust every worker and bring the service down. The cap `SQLParseError` exception is delivered to the caller, but only *after* the CPU work is already burnt.\n\n### Impact\n\n- Single-threaded service: 1-2 KB payload locks the worker for 1-10 seconds (CWE-1333 / CWE-405 / CWE-400 \u2014 uncontrolled resource consumption).\n- Multi-worker service: attacker sends `N` parallel requests, exhausts the worker pool.\n- Wire-to-CPU amplification on the worst vector: ~5000x (2 KB request \u2192 10 seconds CPU).\n- Downstream library impact: `sql-metadata.Parser(sql).columns` calls `sqlparse.parse` internally and inherits the exact same hang (`nested-paren n=1000` \u2192 11.3 s).\n\n### Suggested fix\n\nReplace the eager `str(self)` materialization with a single-pass concatenation of children\u0027s already-cached `value` fields. The `Token.value` invariant `value == str(self) at construction` is preserved (children\u0027s `value` is itself built the same way bottom-up), but the per-node cost drops from `O(subtree)` to `O(len(self.tokens))`:\n\n```python\ndef __init__(self, tokens=None):\n self.tokens = tokens or []\n [setattr(token, \u0027parent\u0027, self) for token in self.tokens]\n # Avoid materializing the full subtree via str(self): concatenating\n # children\u0027s already-cached `value` is O(len(tokens)) per group,\n # whereas str(self) recursively flattens the entire subtree which is\n # O(subtree) per node and turns nested grouping into O(n * depth).\n super().__init__(None, \u0027\u0027.join(token.value for token in self.tokens))\n self.is_group = True\n```\n\nMeasured against the 0.5.5 source tree with the patch applied locally and the full existing test-suite running (479 passed, 2 xfailed, 1 xpassed; the same baseline as unpatched `0d24023`):\n\n| Vector | Before fix | After fix | Speedup |\n|---|---|---|---|\n| nested-paren n=500 | 1336 ms | 11 ms | 121x |\n| nested-paren n=1000 | 11206 ms | 22 ms | 509x |\n| nested-paren n=2000 | TIMEOUT (\u003e10 s) | 45 ms | 220x+ |\n| CASE-nested n=200 | 559 ms | 25 ms | 22x |\n| CASE-nested n=500 | TIMEOUT (\u003e10 s) | 61 ms | 160x+ |\n| benign 1 KB SQL | 3 ms | 3 ms | unchanged |\n\nEnd-to-end Flask `victim_app` re-run against the patched library:\n\n```\n nested-paren n=1000 2008B server= 34.6ms\n nested-paren n=2000 4008B server= 67.2ms\n CASE-nested n=400 13905B server= 49.5ms\n benign 1 KB SQL 220B server= 3.4ms\n```\n\nThe IN-tuple `format()` vector observed at `n=1000` (3.8 s for ~10 KB input) is a separate quadratic in the `reindent` filter (`filters/reindent.py:_get_offset` \u2192 `_flatten_up_to_token`) and is not covered by this advisory; please consider it as a follow-up if the maintainer would like a separate report.\n\n### Fix PR\n\nA fix PR against the temp private fork, mirroring the diff above with a regression test (`test_nested_paren_within_cap_under_50ms`), is attached and linked from this advisory.\n\n### Credit\n\nReported by [tonghuaroot](https://github.com/tonghuaroot).",
"id": "GHSA-pwgv-4x5q-6m9f",
"modified": "2026-08-17T17:49:47Z",
"published": "2026-08-17T17:49:47Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/andialbrecht/sqlparse/security/advisories/GHSA-pwgv-4x5q-6m9f"
},
{
"type": "WEB",
"url": "https://github.com/andialbrecht/sqlparse/commit/939b129e24c0ad5d51368b1aa72fffcaca76f06f"
},
{
"type": "PACKAGE",
"url": "https://github.com/andialbrecht/sqlparse"
}
],
"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": "sqlparse: TokenList.__init__ materializes O(subtree) value per group, causing CPU DoS before depth/token caps trigger"
}
GHSA-Q2H6-GHWM-5QM8
Vulnerability from github – Published: 2026-06-25 21:29 – Updated: 2026-06-25 21:29Summary
InterfaceLookupFormatter<TKey,TElement> constructs an internal Dictionary<TKey, IGrouping<TKey,TElement>> with the default equality comparer instead of the security-aware comparer supplied by options.Security.GetEqualityComparer<TKey>().
Other hash-based collection formatters use the security-aware comparer when MessagePackSecurity.UntrustedData is configured. This formatter omission allows hash-collision CPU denial of service against ILookup<TKey,TElement> even when the application has opted into the untrusted-data security posture.
Impact
Applications are affected when they deserialize untrusted payloads into schemas containing ILookup<TKey,TElement> with a key type for which attacker-controlled hash collisions are feasible.
Under the default comparer, many colliding keys can degrade dictionary insertion from amortized constant time to quadratic behavior. A payload of colliding keys can consume CPU for a disproportionate amount of time. This bypasses the mitigation that developers intentionally enabled by using MessagePackSecurity.UntrustedData.
Affected components
- Package:
MessagePack - API:
InterfaceLookupFormatter<TKey,TElement>.Create - Data type:
ILookup<TKey,TElement> - Finding ID:
MESSAGEPACKCSHARP-041
Patches
Fixes are prepared and will be released in coordinated patch versions.
Upgrade guidance:
- Upgrade
MessagePackto the patched version for your release line. - Upgrade companion MessagePack packages in the same dependency graph to the coordinated patched versions.
The fix should create the internal dictionary with options.Security.GetEqualityComparer<TKey>(), matching the sibling dictionary and lookup formatter behavior.
Workarounds
Patching is recommended.
Until a patched version is available, avoid exposing ILookup<TKey,TElement> in DTOs that deserialize untrusted data. Use collection shapes that are already protected by the security-aware comparer path, or validate and cap collection sizes at the transport boundary.
Resources
MESSAGEPACKCSHARP-041:InterfaceLookupFormattermissing security comparer- CWE-407: Inefficient Algorithmic Complexity
{
"affected": [
{
"package": {
"ecosystem": "NuGet",
"name": "MessagePack"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.5.301"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "MessagePack"
},
"ranges": [
{
"events": [
{
"introduced": "3.0"
},
{
"fixed": "3.1.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-48516"
],
"database_specific": {
"cwe_ids": [
"CWE-407"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-25T21:29:39Z",
"nvd_published_at": "2026-06-22T22:16:48Z",
"severity": "MODERATE"
},
"details": "## Summary\n\n`InterfaceLookupFormatter\u003cTKey,TElement\u003e` constructs an internal `Dictionary\u003cTKey, IGrouping\u003cTKey,TElement\u003e\u003e` with the default equality comparer instead of the security-aware comparer supplied by `options.Security.GetEqualityComparer\u003cTKey\u003e()`.\n\nOther hash-based collection formatters use the security-aware comparer when `MessagePackSecurity.UntrustedData` is configured. This formatter omission allows hash-collision CPU denial of service against `ILookup\u003cTKey,TElement\u003e` even when the application has opted into the untrusted-data security posture.\n\n## Impact\n\nApplications are affected when they deserialize untrusted payloads into schemas containing `ILookup\u003cTKey,TElement\u003e` with a key type for which attacker-controlled hash collisions are feasible.\n\nUnder the default comparer, many colliding keys can degrade dictionary insertion from amortized constant time to quadratic behavior. A payload of colliding keys can consume CPU for a disproportionate amount of time. This bypasses the mitigation that developers intentionally enabled by using `MessagePackSecurity.UntrustedData`.\n\n## Affected components\n\n- Package: `MessagePack`\n- API: `InterfaceLookupFormatter\u003cTKey,TElement\u003e.Create`\n- Data type: `ILookup\u003cTKey,TElement\u003e`\n- Finding ID: `MESSAGEPACKCSHARP-041`\n\n## Patches\n\nFixes are prepared and will be released in coordinated patch versions.\n\nUpgrade guidance:\n\n1. Upgrade `MessagePack` to the patched version for your release line.\n2. Upgrade companion MessagePack packages in the same dependency graph to the coordinated patched versions.\n\nThe fix should create the internal dictionary with `options.Security.GetEqualityComparer\u003cTKey\u003e()`, matching the sibling dictionary and lookup formatter behavior.\n\n## Workarounds\n\nPatching is recommended.\n\nUntil a patched version is available, avoid exposing `ILookup\u003cTKey,TElement\u003e` in DTOs that deserialize untrusted data. Use collection shapes that are already protected by the security-aware comparer path, or validate and cap collection sizes at the transport boundary.\n\n## Resources\n\n- `MESSAGEPACKCSHARP-041`: `InterfaceLookupFormatter` missing security comparer\n- CWE-407: Inefficient Algorithmic Complexity",
"id": "GHSA-q2h6-ghwm-5qm8",
"modified": "2026-06-25T21:29:40Z",
"published": "2026-06-25T21:29:39Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MessagePack-CSharp/MessagePack-CSharp/security/advisories/GHSA-q2h6-ghwm-5qm8"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-48516"
},
{
"type": "PACKAGE",
"url": "https://github.com/MessagePack-CSharp/MessagePack-CSharp"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "MessagePack-CSharp: InterfaceLookupFormatter bypasses collision-resistant comparer settings"
}
No mitigation information available for this CWE.
No CAPEC attack patterns related to this CWE.