Repository navigation
fix(id): escape values assigned through the value setter - #326
Conversation
ID had no value setter, so a programmatically assigned id value was emitted verbatim instead of escaped. ClassName has escaped assigned values since 2018; mirror the same setter on ID.
|
Thanks. This is a real gap, and reusing I ran the branch against This fixes more than the description saysOn an ID parsed with an escape, reassigning const id = parser().astSync('#fo\\o').first.first;
id.value = 'bar';
id.toString(); // main: '#fo\o' branch: '#bar'Your test covers it ( Docs
On the releaseThis changes observable behaviour for existing code: anyone assigning an already-escaped value now gets a double escape. id.value = 'foo\\.bar'; // main: '#foo\.bar' branch: '#foo\\\.bar'That's the same footgun This package sits deep in a lot of dependency trees, so I'd like a second opinion: does minor seem right to you, or would you go major? |
…className Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Updated the description with the raws.value point: on an ID parsed with an escape, assigning On the release: I'd go minor. The old output was invalid selectors, so this is a bug fix, and the double-escape footgun isn't a new hazard, it's the exact one Also pushed a small commit adding notes to |
|
Friendly ping on this when you have time. The description and the API.md notes you asked for are in, and it still merges cleanly. |
|
I will look into it soon, don't worry ! Thanks for your patience. |
`cssesc` stopped being an external dependency on `main` after this branch was opened: it is vendored at `src/util/cssesc` now, so the bare specifier no longer resolved and the suite failed to load.
|
I pushed one commit to your branch. The import now points at the vendored copy, nothing else changed, and I did that rather than asking you to rebase, since it was our change that broke yours. Tell me if you would rather handle it yourself and I will revert my commit. |
* origin/main: feat: support the case-sensitive attribute flag (s) per Selectors Level 4 (postcss#327) fix: escape values assigned to an id through the value setter (postcss#326) fix: escape class values supplied to the constructor (postcss#349) fix: preserve the spaces declared on selector and root containers (postcss#356) fix: forward the default options given to the parser factory (postcss#345) 7.1.8 fix: remove four more quadratic paths from selector parsing # Conflicts: # src/parser.js
* origin/main: fix: preserve selector delimiters after escaped backslashes (postcss#354) fix: keep the processor's entry points usable when destructured feat: support the case-sensitive attribute flag (s) per Selectors Level 4 (postcss#327) fix: escape values assigned to an id through the value setter (postcss#326) fix: escape class values supplied to the constructor (postcss#349) fix: preserve the spaces declared on selector and root containers (postcss#356) fix: forward the default options given to the parser factory (postcss#345) 7.1.8 fix: remove four more quadratic paths from selector parsing chore(deps): bump tinypool and oxfmt (postcss#351) 7.1.7 docs: add CVE-2026-104844 to the 7.1.6 changelog entry fix: keep whitespace around the namespace separator in attribute selectors (postcss#339) fix: invalidate stale raw spelling on combinator value assignment (postcss#342) fix: set parents for all variadic inserted nodes (postcss#343) Consume whitespace after hexadecimal CSS escapes (postcss#340) fix: lossless mode drops whitespace when a selector ends empty (postcss#337) chore(deps-dev): bump source-map-js from 1.2.1 to 1.2.2 (postcss#347) 7.1.6 fix: parse flat selectors in linear time, closing a CPU exhaustion vulnerability # Conflicts: # src/parser.js
IDdoesn't overridevalue, so assigning toid.valuestores the string as-is andtoString()emits it unescaped.ClassNamehas had an escapingvaluesetter sinced4dda8c5("Escape class name values by default", 2018), butIDnever got the same one, even though class and id selectors are both identifiers and follow the same escaping rules.The result is wrong output for any id value that contains characters needing escapes:
Leading digits, spaces and
#break the same way:#1abc,#a b,#a#b.This also fixes a second, worse symptom: on an ID that was parsed with an escape, reassigning
valuepreviously had no effect at all, becauseraws.valuesurvived the assignment andtoString()kept emitting the old escaped string:The new setter stores through
raws, so staleraws.valueis replaced on assignment (the test assertsid.rawsgoes back to{}).This adds the same setter
ClassNameuses (cssesc(v, { isIdentifier: true })stored intoraws.value), so id values escape on assignment:The new test mirrors the existing
ClassName#set valuetest.npm testpasses (lint, typecheck, full suite).