@redocly/chokidar
v3.6.0
Published
Fork of chokidar 3.6.0 with the braces dependency removed (GHSA-vfj7-8cjw-p6xm). Keeps native fsevents on macOS.
Readme
@redocly/chokidar
A fork of chokidar 3.6.0 with the
braces dependency removed. Used by Redocly Realm
and the other Redocly documentation products as a drop-in replacement for
chokidar.
Why this exists
braces (every version up to and including 3.0.3) has a stack-exhaustion
denial-of-service issue, GHSA-vfj7-8cjw-p6xm
(CVE-2026-93687), with no fixed release at the time of writing. Dependency
scanners report it against any project that installs chokidar 3.
Upgrading chokidar is not an option. chokidar 4.0.0
removed the native fsevents binding
on macOS and falls back to fs.watch, which opens one file descriptor per
watched file. On large content trees this fails with EMFILE: too many open
files (#1369,
#1385). The maintainer has
said restoring fsevents is a "no-go" without a new maintainer, and no 4.x or
5.x release includes it.
chokidar 3 only ever called braces from one place, WatchHelper.getDirParts,
and only when the watch path itself is a glob containing {. This fork
replaces that call with a small expander of its own.
What changed from upstream
Three files differ from chokidar 3.6.0; everything else is byte-for-byte upstream.
lib/expand-braces.js(new): mirrorsbraces.expand()for alternation, nesting, escapes, and numeric/alpha/padded/stepped ranges. Keeps the same limitsbraceshad (10,000 chars input, 1,000 items per range) and adds the guard it lacked: nesting is capped at 100 levels, which is the fix the advisory recommends. Endpoints beyondNumber.MAX_SAFE_INTEGERare rejected.index.js: imports the expander instead ofbraces. A pattern that trips any limit is reported through the watcher'serrorevent (deferred one tick so callers can attach a listener, and skipped if the watcher was closed in the meantime) and the path is treated as a literal. Upstream let the error escape from an async context and kill the process.package.json:bracesremoved from dependencies.fseventsis unchanged.
Known divergences from braces, none reachable from a sane watch path:
- A trailing lone backslash is kept (
bracesemits the stringundefined). - A mixed numeric/alpha range such as
{1..a}stays literal.
To see the exact diff:
npm pack [email protected] --pack-destination /tmp && tar -xzf /tmp/chokidar-3.6.0.tgz -C /tmp
diff -r /tmp/package . -x .git -x node_modules -x scripts -x test -x .githubUsage
Alias it under the chokidar name so existing imports keep working:
{
"dependencies": {
"chokidar": "npm:@redocly/[email protected]"
}
}import chokidar from 'chokidar'; // resolves to this packageThe API is identical to chokidar 3.6.0.
Testing
npm install
npm test # unit tests for the brace expander
npm run test:upstream # chokidar 3.6.0's own test suite, run against this forkThe upstream suite (227 tests) passes with no failures, identical to stock
3.6.0. The expander is additionally pinned to braces.expand() output on every
pattern in test/expand-braces.test.js.
Versioning
Versions track upstream: 3.6.0 here is chokidar 3.6.0 plus the changes above.
Fixes to the fork itself bump the patch version (3.6.1, 3.6.2, …).
Publishing
npm version patch # or leave at 3.6.0 for the first publish
npm publish # publishConfig.access is already "public"When to retire this
As soon as upstream braces ships a fix (follow
micromatch/braces#70):
- In consumers, switch the
chokidardependency back to3.6.0from npm. chokidar's ownbraces ~3.0.2range picks up the fix automatically. - Deprecate this package on npm with a message pointing at the fixed
braces. - Archive this repository.
License
MIT, same as upstream. The original copyright notice is preserved in
LICENSE. chokidar is by Paul Miller and contributors; this fork
is maintained by Redocly.
