Files
msd-core/gsd-core/bin/lib/vendor
Tom Boucher 895d9df96d fix(#3477): run untrusted key_links patterns on a linear-time engine (#3496)
`cmdVerifyKeyLinks` compiled `must_haves.key_links[].pattern` from plan frontmatter with `new RegExp()` and tested it against whole file contents, so a nested-quantifier pattern such as `(a+)+$` hung `verify-phase` indefinitely (CWE-1333). JavaScript has no regex-execution timeout.

Untrusted patterns now run on RE2 (re2js), whose match time is linear in input length — the class is closed by the engine, not by a heuristic screen. The screen lost in the ADR-0174 consolidation was deliberately NOT restored: it never worked, since `(a|a)*$`, `((a+))+$`, `(a+){2,}$` and `(a{1,3})+$` all evade it. A refused pattern's matcher returns false for every input, so it cannot report a match no matter what the caller does.

The engine is vendored at gsd-core/bin/lib/vendor/re2js.cjs because gsd-core/bin/** is copied into installed trees with no node_modules; runtime dependencies are unchanged. New ESLint rule local/no-external-require-in-bin enforces that invariant, which had been documented in a comment since the #3024/#2071 bug class and enforced nowhere.

Backreferences and look-around are unsupported by RE2 by construction — disclosed in a Changed changeset.

Closes #3477

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 14:34:36 -04:00
..

vendor/

This directory holds verbatim, unmodified copies of third-party build artifacts that gsd-core/bin/** needs at runtime.

Why

gsd-core/bin/** is copied by the installer into trees that have no node_modules (e.g. ~/.claude/gsd-core/). Any external (non-relative, non-builtin) require()/import under gsd-core/bin/** breaks verify (and everything else) for every installed user, because the module simply cannot be resolved there. The fix is to vendor the compiled artifact in-tree instead of depending on it being installed as an npm package. eslint-rules/no-external-require-in-bin.cjs enforces this at lint time.

Contents

  • re2js.cjs — verbatim copy of node_modules/re2js/build/index.cjs (upstream package re2js, pinned version see package.json devDependencies.re2js). Used by src/pattern.cts (compiled to gsd-core/bin/lib/pattern.cjs) for linear-time RE2 pattern compilation.
  • re2js.d.cts — verbatim copy of node_modules/re2js/build/index.d.cts, so TypeScript resolves types for the relative import from src/pattern.cts.

Do not hand-edit

These files are verbatim copies of the upstream build output. Never edit them directly — refresh them from node_modules instead:

cp node_modules/re2js/build/index.cjs gsd-core/bin/lib/vendor/re2js.cjs
cp node_modules/re2js/build/index.d.cts gsd-core/bin/lib/vendor/re2js.d.cts

node scripts/lint-vendored-deps.cjs fails CI if the vendored copy drifts byte-for-byte from node_modules/re2js/build/ or from the re2js version pinned in package.json devDependencies.