Skip to content

Candidate class row-constructor crashes compile with TypeError: X.map is not a function (prototype-pollution-style lookup on staticValues) #19951

@JoaoHNunes

Description

@JoaoHNunes

Summary

Scanning a source file containing the substring row-constructor (even inside a code comment) crashes Tailwind's compile step with a minified TypeError: X.map is not a function. Root cause appears to be a prototype-pollution-style lookup on a plain-object staticValues map inside the row-* utility's
compile function.

Environment

  • tailwindcss: 4.1.18
  • @tailwindcss/cli: 4.1.18
  • Node: v25.2.1
  • OS: macOS (Darwin arm64)

Minimal Reproduction

mkdir tw-repro && cd tw-repro          
npm init -y                    
npm i -D tailwindcss@4.1.18 @tailwindcss/cli@4.1.18
printf '@import "tailwindcss";\n' > input.css                                                                                                             
printf 'const x = "row-constructor";\n' > candidate.ts
npx @tailwindcss/cli -i input.css -o output.css                                                                                                           

Expected

Compile succeeds. row-constructor is not a valid row-* utility value and should be ignored (same as row-notathing, which works fine).

Actual

≈ tailwindcss v4.1.18          
                      
TypeError: V.map is not a function    

Full stack from a Turbopack dev run on the same source:

TypeError: E.map is not a function
    at Object.compileFn (.../tailwindcss/dist/lib.js:10:20844)
    at Ca (.../tailwindcss/dist/lib.js:16:38197)
    at Li (.../tailwindcss/dist/lib.js:16:37080)                                                                                                          
    at U.factory (.../tailwindcss/dist/lib.js:16:28513)
    at U.get (.../tailwindcss/dist/lib.js:1:8654)                                                                                                         
    at Object.compileAstNodes (.../tailwindcss/dist/lib.js:16:29208)
    at Te (.../tailwindcss/dist/lib.js:16:36451)                                                                                                          
    at Object.build (.../tailwindcss/dist/lib.js:38:1179)
    at Object.Once (.../@tailwindcss/postcss/dist/index.js:10:5864)                                                                                       

Root Cause (hypothesis)

Inside the compile path for the row-* utility, a lookup like:

let E = g.staticValues[b.value.value];                                                                                                                    
if (E) return E.map(ee);

runs against staticValues held as a plain object (not Object.create(null)). When the candidate's value is constructor, the lookup falls through to
Object.prototype.constructor — the Object function — which is truthy but not an array, so .map() throws.

Scope / Other Affected Tokens

Confirmed crashing:

  • row-constructor

Confirmed not crashing (tested on the same setup, so the bug is utility-specific — probably only utilities whose static-values map is a plain object):

  • text-constructor, font-constructor, text-toString, text-hasOwnProperty, text-__proto__

Likely also affected: any row-<Object.prototype key> — e.g. row-toString, row-hasOwnProperty, row-valueOf.

Suggested Fix

Either:

  1. Construct the staticValues map with Object.create(null), so inherited keys are not accessible; or
  2. Gate the lookup with Object.hasOwn(g.staticValues, key) before reading.

Why this matters in practice

The candidate extractor scans any string in any source file, including comments. Our codebase crashed because of a SQL-flavored comment:

// grows switch to a row-constructor IN — e.g.                                                                                                            

That's a plausible substring to appear naturally in prose or docs, and the failure mode is a minified X.map is not a function with no indication of
which candidate triggered it — hard to diagnose without bisecting source files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions