Bump transitive brace-expansion to patched versions (CVE-2026-13149) - #4294
Merged
Conversation
Resolves the brace-expansion DoS advisory (CVE-2026-13149) by upgrading the transitive 1.x and 2.x copies to patched releases via npm audit fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
📊 Performance Test ResultsComparing 032fa2b vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
youknowriad
reviewed
Jul 23, 2026
| import { createRequire as __bundleCreateRequire } from 'node:module'; | ||
| const require = __bundleCreateRequire(import.meta.url); | ||
| import{d as p}from"./chunk-3QFGXLW4.mjs";import"./chunk-2JVHGDER.mjs";import"./chunk-Y7SDG6HL.mjs";import"./chunk-4TKBPMF4.mjs";import{existsSync as d,readFileSync as g,readdirSync as x}from"node:fs";import{join as r}from"node:path";function u(t="<outputDir> [args...]"){let e=process.argv[2];return e||(console.error(`usage: tsx scripts/${h()} ${t} (e.g. output/www.example.com)`),process.exit(1)),e}function h(){return process.argv[1]?.split("/").pop()??"<script>.ts"}var f=u(),s=r(f,"theme","patterns"),m=r(f,"html");function w(t){return t.replace(/<script\b[\s\S]*?<\/script>/gi," ").replace(/<style\b[\s\S]*?<\/style>/gi," ").replace(/<noscript\b[\s\S]*?<\/noscript>/gi," ").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim()}function S(t){return[...t.matchAll(/\b(?:alt|title|aria-label)=["']([^"']*)["']/gi)].map(e=>e[1].trim()).filter(Boolean)}var $=t=>t.replace(/\.php$/i,"").replace(/^page-/,""),n=[],i=[];for(let t of x(s).filter(e=>e.endsWith(".php"))){let e=$(t),l=r(m,`${e}.html`);if(!d(l)){i.push(`${t} (no source html/${e}.html)`);continue}let c=g(l,"utf8"),a=w(c);n.push({slug:`${t}`,php:g(r(s,t),"utf8"),spec:{interactionModel:"static",expectedAssets:[],expectedText:[a,...S(c)],bodyText:[a]}})}n.length===0&&(console.error(`no pattern\u2194source-html pairs found under ${s} / ${m}`),process.exit(1));var o=p({patterns:n});console.log(`validated ${n.length} pattern(s); skipped ${i.length}`);for(let t of i)console.log(` skipped: ${t}`);console.log("ok:",o.ok);console.log("errors:",JSON.stringify(o.errors,null,2));console.log("warning count:",o.warnings.length);var y=o.warnings.filter(t=>!/possible non-source content/.test(t.message));console.log("non-word-noise warnings:",JSON.stringify(y,null,2)); | ||
| import{d as p}from"./chunk-5TGR3JN3.mjs";import"./chunk-2JVHGDER.mjs";import"./chunk-Y7SDG6HL.mjs";import"./chunk-4TKBPMF4.mjs";import{existsSync as d,readFileSync as g,readdirSync as x}from"node:fs";import{join as r}from"node:path";function u(t="<outputDir> [args...]"){let e=process.argv[2];return e||(console.error(`usage: tsx scripts/${h()} ${t} (e.g. output/www.example.com)`),process.exit(1)),e}function h(){return process.argv[1]?.split("/").pop()??"<script>.ts"}var f=u(),s=r(f,"theme","patterns"),m=r(f,"html");function w(t){return t.replace(/<script\b[\s\S]*?<\/script>/gi," ").replace(/<style\b[\s\S]*?<\/style>/gi," ").replace(/<noscript\b[\s\S]*?<\/noscript>/gi," ").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim()}function S(t){return[...t.matchAll(/\b(?:alt|title|aria-label)=["']([^"']*)["']/gi)].map(e=>e[1].trim()).filter(Boolean)}var $=t=>t.replace(/\.php$/i,"").replace(/^page-/,""),n=[],i=[];for(let t of x(s).filter(e=>e.endsWith(".php"))){let e=$(t),l=r(m,`${e}.html`);if(!d(l)){i.push(`${t} (no source html/${e}.html)`);continue}let c=g(l,"utf8"),a=w(c);n.push({slug:`${t}`,php:g(r(s,t),"utf8"),spec:{interactionModel:"static",expectedAssets:[],expectedText:[a,...S(c)],bodyText:[a]}})}n.length===0&&(console.error(`no pattern\u2194source-html pairs found under ${s} / ${m}`),process.exit(1));var o=p({patterns:n});console.log(`validated ${n.length} pattern(s); skipped ${i.length}`);for(let t of i)console.log(` skipped: ${t}`);console.log("ok:",o.ok);console.log("errors:",JSON.stringify(o.errors,null,2));console.log("warning count:",o.warnings.length);var y=o.warnings.filter(t=>!/possible non-source content/.test(t.message));console.log("non-word-noise warnings:",JSON.stringify(y,null,2)); |
Contributor
There was a problem hiding this comment.
Why do we have these "dist" files in the repo? can't we use npm dependencies instead?
Contributor
Author
There was a problem hiding this comment.
It seems it was done for Claude Code and Codex plugin purposes. See #4011
Contributor
Contributor
There was a problem hiding this comment.
(Regardless, it shouldn't block the current PR though)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues
How AI was used in this PR
Claude Code investigated the Dependabot alert, mapped the full set of vulnerable
brace-expansioncopies in the lockfile, determined that api-coding-agentversion bump could not resolve the nested copy (npm re-pins the same resolution), and applied the lockfile-only fix. All findings were verified againstnpm auditand typecheck.Proposed Changes
brace-expansionhad a high-severity DoS advisory (CVE-2026-13149): a tiny crafted input can hang the calling thread for minutes via exponential-time brace expansion. Studio pulled it in transitively across several dependency trees at unpatched versions.This upgrades those transitive copies to patched releases (
1.1.16,2.1.2, and5.0.7where npm can move them), closing alerts #290 (the2.xrange) and #289 (the1.xrange). The change is lockfile-only — no manifest or app-code changes — so there is no user-visible behavior change; it removes a potential denial-of-service vector in dev/build and runtime dependency chains.npm audit fixalso carried a handful of other in-range transitive security patches (body-parser, fast-uri, fast-xml-parser, protobufjs) in the same pass.One
brace-expansion@5.0.6copy bundled deep inside@earendil-works/pi-coding-agent(Dependabot alert #288) is intentionally left untouched here — npm will not upgrade that nested resolution in place, and forcing it would require a package-wideoverride. It can be addressed separately.Testing Instructions
npm run typecheckpasses across all workspaces.npm auditno longer reportsbrace-expansionin the1.xor2.xranges; the only remaining match is thepi-coding-agentnested5.0.6copy (alert Release 1.0.5-beta1 #288).node_modulesversions match the updated lockfile.Pre-merge Checklist