Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Attribute selector with no valid attribute name throws a raw TypeError, or emits the text "undefined"

Open
#334 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
javascript
Domain
tooling

Research direction

Start in src/parser.js at Parser#attribute and reproduce the listed selectors, including [ns|] and [ * ]. Compare the results with the existing [] parser error; done means invalid attribute selectors consistently produce the parser's own error, without a raw TypeError or literal "undefined" output.

Written by the indexing model from the issue text.

Description

Parser#attribute looks ahead to the next token without checking that one exists, and never verifies that an attribute name was actually captured. Two symptoms follow.

1. Raw TypeError when the last token before ] is *, $, ^, ~ or |

const parser = require("postcss-selector-parser");

parser().astSync("[ns|*]");
// TypeError: Cannot read properties of undefined (reading '0')
//     at Parser.attribute (dist/parser.js:255:29)

Same crash for [a*], [a$], [a^], [a~], [a|], [|*], [*|*], [a|*], [ns|$], [ns|^].

These inputs are invalid CSS, so an error is correct, but it should be the parser's own error rather than a TypeError escaping from internals. This is the same class of defect as #329, at a different site: there the token stream ran out before a closing bracket, here it runs out before the lookahead in the token loop.

The four unguarded reads are in src/parser.js inside attribute():

case tokens.asterisk:
  if (next[TOKEN.TYPE] === tokens.equals) {        // next may be undefined
case tokens.caret:                                  // reached by dollar via fall-through
  if (next[TOKEN.TYPE] === tokens.equals) {        // next may be undefined
case tokens.combinator:
  if (content === "~" && next[TOKEN.TYPE] === tokens.equals) {   // next may be undefined
  ...
  if (next[TOKEN.TYPE] === tokens.equals) {        // next may be undefined

Two other reads of next[TOKEN.TYPE] in the same file already guard with next &&, so the pattern is established. The else if immediately below the asterisk case also guards with && next, which suggests the possibility was known at the time.

2. The literal string undefined in the output when no attribute name is captured

parser().astSync("[ * ]").toString();
// "[ *|undefined]"        <- an attribute name of "undefined", and a "|" that was never written

parser().astSync("[  *  ]").toString();
// "[  *|undefined]"

attribute() ends with this.newNode(new Attribute(node)) with no check that node.attribute was ever set. When it was not, Attribute#toString interpolates the missing value, so a selector containing the text undefined is emitted. [*] on its own already throws Expected an attribute., so the two are inconsistent.

Guarding the four lookaheads alone converts most of the crashes in the first section into this second failure instead, so the two need addressing together.

Scale

Comparing 43,200 generated attribute selectors against 7.1.5:

  • 341 produce a raw TypeError
  • 596 produce output containing the literal text undefined

Expected

An attribute selector with no valid attribute name should produce the parser's own error, consistent with [*], rather than a TypeError or a stringified undefined.

Version

Reproduced on 7.1.5 (current latest) and on main at e33e9bc.

Dominant language
JavaScript
Stars
214
Forks
63
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from postcss/postcss-selector-parser

All issues in postcss/postcss-selector-parser

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.