Parent: #1936
Problem
labelPatternToRegExp (src/scoring/preview.ts ~line 975) compiles a registry-supplied label_multipliers key into a RegExp via unbounded chained-wildcard translation, with no length/complexity cap — the exact class of bug #2445 fixed in src/signals/change-guardrail.ts's globToRegExp (which caps chained wildcard groups, where a ** pair counts as one group, at 2, after benchmarking showed 3+ groups causes catastrophic backtracking: 35s at just 1614 chars for 4 chained ** groups). This sibling function was never patched.
Provenance: src/registry/sync.ts fetches registry JSON from api.gittensor.io (or the GITTENSOR_REGISTRY_URL fallback); src/registry/normalize.ts (~lines 56-64) copies label_multipliers keys verbatim into RegistryRepoConfig.labelMultipliers with zero validation. A PR whose GitHub labels include a near-miss string of similar length then hits selectLabelMultiplier → labelPatternToRegExp → RegExp.test(). Benchmarked locally at ~7.7s for 60 wildcard groups against a 66-char near-miss label, growing exponentially with group count. Reachable via the public scoring-preview API (routes.ts buildScorePreview), the MCP tool, and the per-PR label-audit signal (signals/engine.ts labelMatchesPattern) — so one bad registry entry can hang scoring for every PR on that repo.
Fix
Reuse or mirror change-guardrail.ts's hasUnsafeWildcardCount/MAX_GLOB_WILDCARD_GROUPS pattern inside labelPatternToRegExp: count wildcard groups in the incoming pattern and short-circuit to a safe never-match RegExp once the count exceeds the same empirically-safe threshold, before calling new RegExp(). Consider also capping label_multipliers key length during registry normalization (src/registry/normalize.ts ~lines 56-64).
Regression tests
- A
label_multipliers key with more than the safe wildcard-group threshold compiles to a safe never-match regex instead of hanging.
- Legitimate label patterns within the safe threshold continue to match correctly.
- A benchmark/timing-bound test proves compilation + match stays well under a sane budget even for an adversarial near-miss input.
Parent: #1936
Problem
labelPatternToRegExp(src/scoring/preview.ts~line 975) compiles a registry-suppliedlabel_multiplierskey into aRegExpvia unbounded chained-wildcard translation, with no length/complexity cap — the exact class of bug #2445 fixed insrc/signals/change-guardrail.ts'sglobToRegExp(which caps chained wildcard groups, where a**pair counts as one group, at 2, after benchmarking showed 3+ groups causes catastrophic backtracking: 35s at just 1614 chars for 4 chained**groups). This sibling function was never patched.Provenance:
src/registry/sync.tsfetches registry JSON fromapi.gittensor.io(or theGITTENSOR_REGISTRY_URLfallback);src/registry/normalize.ts(~lines 56-64) copieslabel_multiplierskeys verbatim intoRegistryRepoConfig.labelMultiplierswith zero validation. A PR whose GitHub labels include a near-miss string of similar length then hitsselectLabelMultiplier→labelPatternToRegExp→RegExp.test(). Benchmarked locally at ~7.7s for 60 wildcard groups against a 66-char near-miss label, growing exponentially with group count. Reachable via the public scoring-preview API (routes.tsbuildScorePreview), the MCP tool, and the per-PR label-audit signal (signals/engine.tslabelMatchesPattern) — so one bad registry entry can hang scoring for every PR on that repo.Fix
Reuse or mirror
change-guardrail.ts'shasUnsafeWildcardCount/MAX_GLOB_WILDCARD_GROUPSpattern insidelabelPatternToRegExp: count wildcard groups in the incoming pattern and short-circuit to a safe never-matchRegExponce the count exceeds the same empirically-safe threshold, before callingnew RegExp(). Consider also cappinglabel_multiplierskey length during registry normalization (src/registry/normalize.ts~lines 56-64).Regression tests
label_multiplierskey with more than the safe wildcard-group threshold compiles to a safe never-match regex instead of hanging.