Skip to content

Fix CVE-2026-9358 (NVD) / SNYK-JS-POSTCSSSELECTORPARSER-16873882#316

Open
MoOx wants to merge 7 commits into
postcss:masterfrom
MoOx:fix-315
Open

Fix CVE-2026-9358 (NVD) / SNYK-JS-POSTCSSSELECTORPARSER-16873882#316
MoOx wants to merge 7 commits into
postcss:masterfrom
MoOx:fix-315

Conversation

@MoOx
Copy link
Copy Markdown
Collaborator

@MoOx MoOx commented Jun 4, 2026

Closes #315

The fix basically prevent stack overflow on deeply nested selectors (CVE-2026-9358)

Deeply nested selectors (e.g. :not(:not(:not(…)))) caused uncontrolled recursion in both parsing and toString() serialization, overflowing the call stack with an uncatchable RangeError (CWE-674 / SNYK-JS-POSTCSSSELECTORPARSER-16873882).

Add a nesting-depth limit (default 256, far beyond any real selector) that raises a clear, catchable Error instead of crashing:

  • bound parenthesis nesting during parsing
  • bound recursion during pseudo serialization
  • expose a configurable maxNestingDepth parser option

Copilot AI review requested due to automatic review settings June 4, 2026 12:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds AVA regression coverage to ensure deeply nested selectors no longer cause uncontrolled recursion/stack overflow (CVE-2026-9358 / SNYK-JS-POSTCSSSELECTORPARSER-16873882), and that failures surface as catchable errors.

Changes:

  • Adds parse-time regression tests for deeply nested :not(...) selectors exceeding the maximum depth.
  • Adds serialization (toString) regression test by building a deep AST that bypasses parsing guards.
  • Adds tests for the maxNestingDepth option (tightening and loosening the limit).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/__tests__/recursion.mjs Outdated
Comment thread src/__tests__/recursion.mjs Outdated
Comment thread src/__tests__/recursion.mjs Outdated
Comment thread src/__tests__/recursion.mjs Outdated
Comment thread src/__tests__/recursion.mjs Outdated
Comment thread src/__tests__/recursion.mjs Outdated
Comment thread src/__tests__/recursion.mjs Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Comment thread src/parser.js Outdated
Comment thread src/parser.js Outdated
Comment thread src/parser.js Outdated
Comment thread src/selectors/pseudo.js Outdated
@MoOx MoOx requested a review from Copilot June 4, 2026 13:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.

Comment thread src/selectors/pseudo.js Outdated
@MoOx MoOx requested a review from Copilot June 4, 2026 13:19
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Comment thread src/processor.js
Comment thread src/selectors/pseudo.js Outdated
@MoOx MoOx requested a review from Copilot June 4, 2026 13:38
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Comment on lines +19 to +21
export default function resolveMaxNestingDepth (value) {
return Number.isSafeInteger(value) && value >= 0 ? value : MAX_NESTING_DEPTH;
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't clamp. maxNestingDepth is trusted developer configuration, never derived from the parsed CSS, so it isn't reachable by an attacker (whose only input is the selector string, already capped by the default of 256). There's also no universally correct ceiling — the safe stack depth is environment-dependent — so a hard clamp would either reject legitimate raised limits or still be unsafe on small stacks. Documented the caveat in the README instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Uncontrolled recursion in toString AST serialization — CVE-2026-9358 / SNYK-JS-POSTCSSSELECTORPARSER-16873882

3 participants