From 39d368612ac737d06921b88d4ce4236fc0da32bf Mon Sep 17 00:00:00 2001 From: Mikael Mattsson <62009528+mikael-mattsson@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:56:23 +0200 Subject: [PATCH] Improve GHSA-rj75-hqrm-r3gf --- .../GHSA-rj75-hqrm-r3gf.json | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/advisories/github-reviewed/2026/10/GHSA-rj75-hqrm-r3gf/GHSA-rj75-hqrm-r3gf.json b/advisories/github-reviewed/2026/10/GHSA-rj75-hqrm-r3gf/GHSA-rj75-hqrm-r3gf.json index 97171b374a2f..8eff9949095a 100644 --- a/advisories/github-reviewed/2026/10/GHSA-rj75-hqrm-r3gf/GHSA-rj75-hqrm-r3gf.json +++ b/advisories/github-reviewed/2026/10/GHSA-rj75-hqrm-r3gf/GHSA-rj75-hqrm-r3gf.json @@ -1,13 +1,13 @@ { "schema_version": "1.4.0", "id": "GHSA-rj75-hqrm-r3gf", - "modified": "2026-10-05T22:53:54Z", + "modified": "2026-10-05T22:53:57Z", "published": "2026-10-05T22:53:54Z", "aliases": [ "CVE-2026-104844" ], "summary": "PostCSS: Quadratic complexity in flat selector parsing allows CPU exhaustion", - "details": "### Impact\n\n`.` and `#` are not word delimiters in the tokenizer, so a flat selector such as\n`.a.a.a...` reaches `splitWord()` as a single word token carrying n class or id\nindexes. Three passes scanned those index arrays linearly for every index,\nmaking the parse O(n^2) in the number of indexes rather than in input length:\n`uniqs()`, the `indices.forEach` loop, and the Sass-interpolation filter.\nParsing a 400 KB flat selector took ~34 s on a modern laptop, fully occupying a\nsingle thread. A benign selector of identical byte size parses in tens of\nmilliseconds, so the cost is driven by the index count, not the input size.\nThe nesting depth of such a selector is 0, so the `maxNestingDepth` guard added\nin 7.1.3 offers no protection.\n\nReachability is deployment dependent. Only consumers that parse untrusted,\nattacker-supplied selectors synchronously in a request path are exposed, for\nexample CSS sanitizers, CSS-in-JS services and online playgrounds. Ordinary\nbuild-time use on trusted sources is not affected.\n\n### Patches\n\nFixed in 7.1.6. The three passes now use Set membership tests, making parsing\nlinear in the number of indexes. There is no behaviour change: parsing is\nbyte-identical on a differential corpus of 8413 selectors.\n\n### Workarounds\n\nCap the size of selectors accepted from untrusted sources before parsing.", + "details": "### Impact\n\n`.` and `#` are not word delimiters in the tokenizer, so a flat selector such as\n`.a.a.a...` reaches `splitWord()` as a single word token carrying n class or id\nindexes. Three passes scanned those index arrays linearly for every index,\nmaking the parse O(n^2) in the number of indexes rather than in input length:\n`uniqs()`, the `indices.forEach` loop, and the Sass-interpolation filter.\nParsing a 400 KB flat selector took ~34 s on a modern laptop, fully occupying a\nsingle thread. A benign selector of identical byte size parses in tens of\nmilliseconds, so the cost is driven by the index count, not the input size.\nThe nesting depth of such a selector is 0, so the `maxNestingDepth` guard added\nin 7.1.3 offers no protection.\n\nReachability is deployment dependent. Only consumers that parse untrusted,\nattacker-supplied selectors synchronously in a request path are exposed, for\nexample CSS sanitizers, CSS-in-JS services and online playgrounds. Ordinary\nbuild-time use on trusted sources is not affected.\n\n### Patches\n\nFixed in 7.1.6, and for the 6.x line in 6.1.5 (backport of the same change,\npostcss/postcss-selector-parser#346). The three passes now use Set membership tests, making parsing\nlinear in the number of indexes. There is no behaviour change: parsing is\nbyte-identical on a differential corpus of 8413 selectors.\n\n### Workarounds\n\nCap the size of selectors accepted from untrusted sources before parsing.", "severity": [ { "type": "CVSS_V3", @@ -25,7 +25,7 @@ "type": "ECOSYSTEM", "events": [ { - "introduced": "0" + "introduced": "7.0.0" }, { "fixed": "7.1.6" @@ -33,6 +33,25 @@ ] } ] + }, + { + "package": { + "ecosystem": "npm", + "name": "postcss-selector-parser" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "0" + }, + { + "fixed": "6.1.5" + } + ] + } + ] } ], "references": [ @@ -44,6 +63,10 @@ "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-104844" }, + { + "type": "WEB", + "url": "https://github.com/postcss/postcss-selector-parser/pull/346" + }, { "type": "WEB", "url": "https://github.com/postcss/postcss-selector-parser/commit/62b191792df0a0bc56062e5a875bc74aae2a51cd" @@ -52,9 +75,17 @@ "type": "PACKAGE", "url": "https://github.com/postcss/postcss-selector-parser" }, + { + "type": "WEB", + "url": "https://github.com/postcss/postcss-selector-parser/releases/tag/6.1.5" + }, { "type": "WEB", "url": "https://github.com/postcss/postcss-selector-parser/releases/tag/7.1.6" + }, + { + "type": "WEB", + "url": "https://www.npmjs.com/package/postcss-selector-parser/v/6.1.5" } ], "database_specific": {