| # postcss-selector-parser |
| |
| [ ](https://www.npmjs.com/package/postcss-selector-parser) |
| [](https://github.com/postcss/postcss-selector-parser/actions) |
| [](https://github.com/postcss/postcss-selector-parser) |
| |
| > Selector parser with built in methods for working with selector strings. |
| |
| ## Install |
| |
| With [npm](https://npmjs.com/package/postcss-selector-parser) do: |
| |
| ``` |
| npm install postcss-selector-parser |
| ``` |
| |
| ## Quick Start |
| |
| ```js |
| const parser = require('postcss-selector-parser'); |
| const transform = selectors => { |
| selectors.walk(selector => { |
| // do something with the selector |
| console.log(String(selector)) |
| }); |
| }; |
| |
| const transformed = parser(transform).processSync('h1, h2, h3'); |
| ``` |
| |
| To normalize selector whitespace: |
| |
| ```js |
| const parser = require('postcss-selector-parser'); |
| const normalized = parser().processSync('h1, h2, h3', {lossless: false}); |
| // -> h1,h2,h3 |
| ``` |
| |
| Async support is provided through `parser.process` and will resolve a Promise |
| with the resulting selector string. |
| |
| ## API |
| |
| Please see [API.md](API.md). |
| |
| ## Security |
| |
| ### Selector nesting depth (CVE-2026-9358) |
| |
| The parser walks the selector AST recursively, both when parsing and when |
| serializing it back to a string (`.toString()`). In versions up to and |
| including `7.1.1`, a selector with extreme nesting — for example thousands of |
| nested `:not(...)` — could recurse deeply enough to overflow the call stack and |
| throw `RangeError: Maximum call stack size exceeded`, a potential |
| denial-of-service when processing untrusted CSS. |
| |
| This is now bounded by a maximum nesting depth (default: `256`). Beyond that |
| depth, parsing and serialization throw a regular, catchable `Error` at a |
| predictable point instead of relying on the runtime hitting its stack limit. |
| The default is far above any realistic selector, so it does not affect normal |
| use. |
| |
| **Practical impact is low.** The only attacker-controlled input is the selector |
| string itself, which is now capped by the default limit. The limit is |
| adjustable through the `maxNestingDepth` option, but that option is trusted |
| configuration provided by the integrating code — it is never derived from the |
| parsed CSS, so a malicious selector cannot change it: |
| |
| ```js |
| // Tighten the limit when parsing untrusted input: |
| parser().processSync(untrustedSelector, {maxNestingDepth: 128}); |
| ``` |
| |
| Raising `maxNestingDepth` to a very large value is an explicit, informed choice |
| and can reintroduce the stack-overflow risk in environments with a small call |
| stack (e.g. browser workers). The default is recommended unless you have a |
| specific need. |
| |
| ## Credits |
| |
| * Huge thanks to Andrey Sitnik (@ai) for work on PostCSS which helped |
| accelerate this module's development. |
| |
| ## License |
| |
| MIT |