npm audit Flags braces in Tailwind v3: There Is No Fix (2026)

npm audit started reporting a High-severity bug in braces in early October, and the usual fix doesn't exist. braces 3.0.3 is the newest release on npm, and 3.0.3 is the vulnerable version. So npm reaches for the only thing it can change. On a Tailwind v3 project, that's Tailwind itself, bumped to v4.

We reproduced it on 2026-10-20 with a fresh Vite + React + Tailwind v3 project and a fresh create-next-app. Here's what the warning means, why --force is the wrong answer, and the one command that gives you an honest audit.

TL;DR

braces through 3.0.3 crashes with a stack overflow on deeply nested patterns (CVE-2026-93687), and no patched release exists. On a Tailwind v3 app, npm audit fix --force "fixes" it by installing Tailwind 4, a breaking upgrade. On Next.js 16 it downgrades eslint-config-next to 14. Both are build-time tools that only feed braces your own config, so there's no production exposure. Run npm audit --omit=dev and leave it.

What the advisory says

GHSA-vfj7-8cjw-p6xm, as of 2026-10-20:

  • Package: braces, every version up to and including 3.0.3. No fixed version is listed.
  • Severity: High, CVSS 3.1 7.5. The only impact scored is availability: no data read, nothing written.
  • Bug: the recursive code that parses, compiles and expands patterns has no depth guard, so "deeply nested brace patterns under the character limit" exhaust the call stack and the process dies "with an uncaught RangeError".
  • Dates: NVD published it on 2026-09-18. GitHub reviewed it into its advisory database on 2026-10-02, which is what npm audit reads, so that's roughly when the warning started showing up. It's a little older than it looks.

The npm registry confirms there's nothing to upgrade to. braces' latest tag is 3.0.3, published 2024-05-21. There is no 3.0.4.

Don't trust a page that tells you to override braces to 3.0.4. At least one vulnerability database lists "versions prior to 3.0.4" as affected. An overrides entry pointing at a version that doesn't exist won't install. Check npm view braces versions before you copy any fix.

We reproduced the crash on Node 22.22.0. braces rejects input over 10,000 characters, but a pattern of 4,999 opening braces, one letter and 4,999 closing braces is 9,999 characters, and it does this:

braces(pattern) RangeError: Maximum call stack size exceeded micromatch.braces(pattern, {expand}) RangeError: Maximum call stack size exceeded micromatch.isMatch('a', pattern) returns normally

That last line matters. isMatch, the call most code actually makes, didn't crash in our test, even with a comma in the middle of the nesting. The crash needs code that calls braces directly, or micromatch.braces.

Why it's in your project

You didn't install braces. Two very common tools did.

Tailwind v3. tailwindcss@3.4.19, the current v3-lts release, depends on chokidar ^3.6.0, fast-glob and micromatch ^4.0.8. chokidar 3.6.0 depends on braces ~3.0.2 directly, and micromatch pulls it in too:

$ npm ls braces -- tailwindcss@3.4.19 +-- chokidar@3.6.0 | -- braces@3.0.3 -- micromatch@4.0.8 -- braces@3.0.3 deduped

Next.js 16, through its lint config. A fresh create-next-app today uses Tailwind v4, which has no dependencies at all. braces still shows up, through a chain of lint tooling: eslint-config-next@16.4.2 requires @next/eslint-plugin-next@16.4.2, which pins fast-glob@3.3.1, which needs micromatch, which needs braces.

What npm audit fix --force actually does

Our Tailwind v3 test project (Vite 5.4, React 18, Tailwind 3.4) reported 9 vulnerabilities, 6 high and 3 moderate. Most of the highs are one problem counted along the chain: braces, then chokidar, micromatch, fast-glob and Tailwind for depending on it. A separate Vite/esbuild dev-server advisory and the postcss-selector-parser one below make up the rest. The braces entry, trimmed:

braces * Severity: high braces vulnerable to stack-exhaustion denial of service through deeply nested patterns fix available via npm audit fix --force Will install tailwindcss@4.3.3, which is a breaking change

npm isn't wrong that this removes braces. Tailwind 4.3.3 lists no dependencies, so there's no chokidar and no micromatch left. But it's a major-version jump on the thing that styles your entire app. Tailwind's upgrade guide says JavaScript config files "are no longer detected automatically in v4". Your theme, custom colours and content paths live in exactly that file in most v3 projects.

On the Next.js project, --force goes the other direction:

fix available via npm audit fix --force Will install eslint-config-next@14.2.35, which is a breaking change

That's a downgrade two majors back, to a lint config written for Next 14, because @next/eslint-plugin-next@14.2.35 happened to use glob instead of fast-glob. We ran it. The forced downgrade cleared braces and replaced it with 3 new high findings from glob 10.3.10 (GHSA-5j98-mcp5-4vw2, a command injection in glob's CLI). npm's suggested fix for that was eslint-config-next@16.4.2, the version you started on, which brings braces straight back. You go round in a circle and end up with a lint config written for Next 14.

This is the command an AI agent will run for you. Ask Cursor or Claude Code to "fix the npm audit warnings" and the obvious move is the one npm prints: npm audit fix --force. On a Tailwind v3 app that's a broken stylesheet with a green audit. If an agent proposes it, say no, and point it at this page.

Does it reach your running app?

For a normal Tailwind or Next.js app, no.

Tailwind v3 runs braces and micromatch at build time, over the content globs you wrote in tailwind.config.js. Unless your config builds those globs from something untrusted, which would be unusual, nothing a visitor sends ever becomes a Tailwind glob. The worst case is a crashed build on your own machine. The same goes for the ESLint plugin, which runs when you lint, not when someone loads a page. Neither one is in your production server's request path.

The case that does matter is your own code. If you've got an endpoint that takes a pattern from the user (a file filter, a search with wildcards, a "match these paths" feature) and hands it to braces() or micromatch.braces(), someone can crash that process with one request. Checking for it takes two minutes:

grep -rnE "(braces|micromatch)'"" --include=.js --include=.ts --include=*.mjs --exclude-dir=node_modules .

No hits means braces only exists in your tooling.

The 5-minute check

1

See where braces comes from. Run npm ls braces. If every path starts at tailwindcss, eslint-config-next, or another build tool, you're in the common case.

2

Confirm those tools are dev dependencies. Open package.json. Tailwind's own v3 install instructions use npm install -D tailwindcss@3, so it's usually under devDependencies. If yours landed in dependencies, move it.

3

Audit what ships. Run npm audit --omit=dev. On both of our test projects it reported found 0 vulnerabilities.

4

Grep your own code with the command above. That's the only place this bug can become a production problem.

The second warning riding along

Tailwind v3 projects will usually see a Moderate warning next to braces: postcss-selector-parser, GHSA-rj75-hqrm-r3gf (CVE-2026-104844), a quadratic-time parse that can pin the CPU. The advisory lists the fix as 7.1.6. Tailwind v3 asks for ^6.1.2, so it can't reach 7.

On 2026-10-19 the maintainers shipped 6.1.5 under a legacy-v6 tag. Its changelog says it backports the fix and calls it "the patched version for the 6.x line", naming Tailwind CSS 3 as the reason the line still exists. A fresh install resolves 6.1.5. But on 2026-10-20 npm audit still flagged it, because the advisory's range still reads "below 7.1.6". So if npm ls postcss-selector-parser shows 6.1.5, you already have the fix and the warning is stale. On an older lockfile, npm update postcss-selector-parser gets you there.

When to actually upgrade

Tailwind 4 is a reasonable move on its own merits, just not as a side effect of an audit command. If you want it, do it on purpose: on a branch, with Tailwind's npx @tailwindcss/upgrade tool, then click through every page. Check the browser floor first, too. The guide says v4 targets Safari 16.4+, Chrome 111+ and Firefox 128+, and tells you to stay on v3.4 if you need older browsers.

Until braces ships a release with a depth limit, there's nothing better to upgrade to. A build-time warning with no fix is something to understand and leave alone, not something to make disappear.

What is the braces vulnerability npm audit is reporting?

GHSA-vfj7-8cjw-p6xm (CVE-2026-93687), rated High. braces through 3.0.3 walks brace patterns recursively with no depth limit, so a deeply nested pattern exhausts the call stack and throws a RangeError. NVD published it on 2026-09-18 and it entered GitHub's reviewed advisory database on 2026-10-02, which is when npm audit started showing it.

Is there a fixed version of braces?

No, not as of 2026-10-20. The latest braces on npm is 3.0.3, published in May 2024, and the advisory lists 3.0.3 as the last affected version. If a page tells you to override braces to 3.0.4, check the registry first: that version doesn't exist.

Why does npm audit fix --force want to install Tailwind 4?

Because Tailwind 4 has no dependencies, so it's the only way npm can remove braces from a Tailwind v3 project. Tailwind v3 pulls braces in through chokidar and micromatch. Moving from v3 to v4 is a major upgrade: Tailwind's own guide says JavaScript config files are no longer detected automatically in v4.

Is my Tailwind v3 app actually vulnerable?

Almost certainly not in production. Tailwind runs braces at build time on the content globs you wrote in your own config, not on anything a visitor sends. The crash needs an attacker-supplied pattern reaching braces, which means your own server code would have to pass user input to braces or micromatch.braces.

How do I make npm audit stop reporting it?

Run npm audit --omit=dev. Tailwind and eslint-config-next are normally devDependencies, and in our test projects that command reported 0 vulnerabilities. That's the honest view of what ships to production. Don't run npm audit fix --force to clear it.

Know what actually ships

npm audit reads your lockfile. CheckYourVibe scans the app you deployed for exposed keys, open databases and missing auth.

Vulnerability Guides

npm audit Flags braces in Tailwind v3: There Is No Fix (2026)