From 808e0b80d0ffa329e74648a402360ecbc8020a1e Mon Sep 17 00:00:00 2001 From: unional Date: Tue, 1 Sep 2026 17:07:01 -0700 Subject: [PATCH] fix(security): bound dev-tree overrides within the major they patch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cross-spawn, lodash, tmp, and the minimatch/brace-expansion overrides for pre-9.0.7 minimatch and pre-1.1.13 brace-expansion had unbounded (or too-loosely bounded) upper ranges, letting a vulnerability fix silently carry a package across one or more majors with nothing to flag it. Bound each to the major it patches, matching the pattern already used for the other overrides in this file (and for cyberuni/iso-error). The only resolution this changes is minimatch@3.1.5's brace-expansion, which drops from 5.0.7 (an unrelated, still-unpatched major pulled in only by the old unbounded target) to 1.1.18, inside the major the override was meant to patch. cross-spawn, lodash, tmp, and minimatch's 9.x override were already no-ops in the resolved tree, so bounding them changes nothing today but stops a future silent jump. brace-expansion@5.0.7 still appears in the lockfile via minimatch@10.2.5 (glob/typedoc's own direct dependency, unrelated to any override) and pnpm audit still reports 2 high vulnerabilities from that path alone — unchanged from before this commit and out of scope here. --- pnpm-lock.yaml | 25 +++++++++++++++++++------ pnpm-workspace.yaml | 15 ++++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3484298..0783a95 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,12 +5,12 @@ settings: excludeLinksFromLockfile: false overrides: - cross-spawn@<6.0.6: '>=6.0.6' + cross-spawn@<6.0.6: ^6.0.6 minimatch@<3.1.4: '>=3.1.4 <4' - minimatch@>=9.0.0 <9.0.7: <11 - lodash@<4.17.24: '>=4.17.24' - brace-expansion@<1.1.13: <6 - tmp@<0.2.6: '>=0.2.6' + minimatch@>=9.0.0 <9.0.7: ^9.0.7 + lodash@<4.17.24: ^4.17.24 + brace-expansion@<1.1.13: ^1.1.18 + tmp@<0.2.6: ^0.2.6 nanoid@<3.3.18: '>=3.3.18 <4' js-yaml@<4.3.1: '>=4.3.1 <5' fast-uri@<3.1.5: '>=3.1.5 <4' @@ -998,6 +998,9 @@ packages: resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==} engines: {node: 20 || >=22} + brace-expansion@1.1.18: + resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==} + brace-expansion@2.1.4: resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} @@ -1046,6 +1049,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + conventional-changelog-angular@9.4.0: resolution: {integrity: sha512-HdxRxuS8bBXVIuo4V82gvSwAXT0vYQUizrjs/izmPg5JdDstr8v8I5hduGL3iQbG+o310dUDxC4+LetuS5hu9w==} engines: {node: '>=22'} @@ -2823,6 +2829,11 @@ snapshots: dependencies: jackspeak: 4.2.3 + brace-expansion@1.1.18: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 @@ -2865,6 +2876,8 @@ snapshots: color-name@1.1.4: {} + concat-map@0.0.1: {} + conventional-changelog-angular@9.4.0: dependencies: '@conventional-changelog/template': 1.4.0 @@ -3301,7 +3314,7 @@ snapshots: minimatch@3.1.5: dependencies: - brace-expansion: 5.0.7 + brace-expansion: 1.1.18 minimatch@7.4.9: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2b6c4e9..52d74cd 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,13 +5,18 @@ allowBuilds: # size-limit's estimator. `@swc/core`, `core-js` and `unrs-resolver` left with jest # and eslint; nothing in the tree pulls them any more. esbuild: true +# All overrides below are deliberately bounded within the major they patch — a +# selector clears a vulnerable range, and the target stays inside that same +# major (or, for a pre-1.0 package, the equivalent minor) so clearing an +# advisory can never silently carry the tree across a major it wasn't asked +# to move to. overrides: - cross-spawn@<6.0.6: '>=6.0.6' + cross-spawn@<6.0.6: '^6.0.6' minimatch@<3.1.4: '>=3.1.4 <4' - minimatch@>=9.0.0 <9.0.7: '<11' - lodash@<4.17.24: '>=4.17.24' - brace-expansion@<1.1.13: '<6' - tmp@<0.2.6: '>=0.2.6' + minimatch@>=9.0.0 <9.0.7: '^9.0.7' + lodash@<4.17.24: '^4.17.24' + brace-expansion@<1.1.13: '^1.1.18' + tmp@<0.2.6: '^0.2.6' # Dev-tree advisories with no upgrade path: every parent is already on its latest # release, so bumping a direct dependency reaches none of them. `path-equal` declares no # runtime dependencies, so none of this ships to consumers — Dependabot's `runtime`