Merge pull request 'fix(security): raise brace-expansion and undici override floors' (#127) from issue-124-125-brace-expansion-undici-floors into master

This commit is contained in:
maximus 2026-10-02 18:14:26 +00:00
commit 35ab0f64ae
3 changed files with 84 additions and 25 deletions

42
package-lock.json generated
View file

@ -3289,9 +3289,9 @@
}
},
"node_modules/@react-native/codegen/node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@ -4338,9 +4338,9 @@
}
},
"node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
@ -6404,9 +6404,9 @@
}
},
"node_modules/expo/node_modules/brace-expansion": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
"integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
"integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@ -10557,9 +10557,9 @@
}
},
"node_modules/react-native/node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@ -10977,9 +10977,9 @@
}
},
"node_modules/rimraf/node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@ -11703,9 +11703,9 @@
}
},
"node_modules/test-exclude/node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@ -11931,9 +11931,9 @@
}
},
"node_modules/undici": {
"version": "6.28.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz",
"integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==",
"version": "6.29.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.29.0.tgz",
"integrity": "sha512-R+RODBqp6i2pPflGdq+xIOUkl+RNfGgHwoinecKu/JCuf2uO06cOKoDbI2P7Dn6KcswdKwrczbU6IYJ6K8X+wg==",
"license": "MIT",
"engines": {
"node": ">=18.17"

View file

@ -73,14 +73,14 @@
"postcss": "^8.5.18",
"js-yaml@^3.0.0": "^3.15.2",
"js-yaml@^4.0.0": "^4.3.2",
"brace-expansion@^1.0.0": "^1.1.18",
"brace-expansion@^2.0.0": "^2.1.4",
"brace-expansion@^5.0.0": "^5.0.9",
"brace-expansion@^1.0.0": "^1.1.21",
"brace-expansion@^2.0.0": "^2.1.7",
"brace-expansion@^5.0.0": "^5.0.12",
"@babel/core": "^7.29.6",
"browserslist": "^4.28.7",
"@expo/cli": {
"ws": "^8.20.1",
"undici": "^6.28.0",
"undici": "^6.28.1",
"tar": "^7.5.21"
},
"react-devtools-core": {

View file

@ -264,6 +264,65 @@ check('@react-navigation/core deep link round trip keeps query params', () => {
assert.equal(getPathFromState(state, config), '/task/abc?x=1&y=a%20b');
});
// --- Override floors for build-tool transitive deps (#124, #125) ---
// brace-expansion is overridden per major (version-scoped): a blanket override
// forces one major onto every minimatch and breaks minimatch@3 (#103). The
// floors below are the patched head of each major; any other major is either
// vulnerable (4.x) or unexpected, and must fail loudly.
function versionAtLeast(version, floor) {
const a = version.split('.').map(Number);
const b = floor.split('.').map(Number);
for (let i = 0; i < 3; i++) {
if (a[i] !== b[i]) return a[i] > b[i];
}
return true;
}
const BRACE_EXPANSION_FLOORS = { 1: '1.1.21', 2: '2.1.7', 5: '5.0.12' };
check('every installed brace-expansion copy is at or above its major floor', () => {
const copies = installedCopies('brace-expansion');
assert.ok(copies.length > 0, 'brace-expansion is not installed');
const strays = copies.filter((c) => {
const floor = BRACE_EXPANSION_FLOORS[majorOf(c.version)];
return !floor || !versionAtLeast(c.version, floor);
});
assert.deepEqual(
strays.map((c) => `${c.version} at ${path.relative(ROOT, c.dir)}`),
[],
`expected floors ${JSON.stringify(BRACE_EXPANSION_FLOORS)}`
);
});
check('every installed undici copy is >= 6.28.1', () => {
const copies = installedCopies('undici');
assert.ok(copies.length > 0, 'undici is not installed');
const strays = copies.filter((c) => !versionAtLeast(c.version, '6.28.1'));
assert.deepEqual(
strays.map((c) => `${c.version} at ${path.relative(ROOT, c.dir)}`),
[],
'undici must be >= 6.28.1'
);
});
// The call that broke under the blanket override: each minimatch copy must
// still expand braces through its own brace-expansion major.
check('every installed minimatch copy still matches globs and braces', () => {
const copies = installedCopies('minimatch');
const majors = [...new Set(copies.map((c) => majorOf(c.version)))].sort();
assert.deepEqual(majors, ['10', '3', '9'], 'expected minimatch majors 3, 9 and 10');
for (const c of copies) {
const mod = require(c.dir);
const minimatch = mod.minimatch || mod; // v3 exports the function itself
const where = `minimatch ${c.version} at ${path.relative(ROOT, c.dir)}`;
assert.equal(minimatch('foo/bar.js', '**/*.js'), true, `${where}: globstar`);
assert.equal(minimatch('a/b.js', 'a/{b,c}.js'), true, `${where}: brace match`);
assert.equal(minimatch('a/d.js', 'a/{b,c}.js'), false, `${where}: brace miss`);
assert.equal(minimatch('f3.js', 'f{1..3}.js'), true, `${where}: numeric range`);
}
});
if (failed === 0) {
console.log('\nsmoke OK');
process.exit(0);