diff --git a/backend/package-lock.json b/backend/package-lock.json index 5fe371fce0..208a2ee8da 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -3808,9 +3808,9 @@ "license": "Apache-2.0" }, "node_modules/fast-uri": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", - "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "funding": [ { "type": "github", @@ -4248,9 +4248,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", "license": "MIT", "engines": { "node": ">= 12" diff --git a/backend/package.json b/backend/package.json index 1efa093dd2..4f7182154e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -44,5 +44,9 @@ "tsx": "^4.19.3", "typescript": "^5.8.3" }, + "overrides": { + "fast-uri": "3.1.5", + "ip-address": "10.4.0" + }, "license": "AGPL-3.0-only" } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d7786ceaab..79b39fef20 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7027,9 +7027,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", - "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -14668,7 +14668,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.28.0", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/frontend/package.json b/frontend/package.json index e9724e5ccf..e5b1b52422 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -77,7 +77,8 @@ "wrangler": "^4.90.0" }, "overrides": { - "brace-expansion": "5.0.8", + "brace-expansion": "5.0.9", + "undici": "7.29.0", "postcss": "8.5.22", "sharp": "0.35.3" }, diff --git a/frontend/scripts/patch-brace-expansion-compat.mjs b/frontend/scripts/patch-brace-expansion-compat.mjs index 9f395bd611..dcb540deab 100644 --- a/frontend/scripts/patch-brace-expansion-compat.mjs +++ b/frontend/scripts/patch-brace-expansion-compat.mjs @@ -15,7 +15,7 @@ const root = resolve(import.meta.dirname, ".."); const lock = JSON.parse( readFileSync(resolve(root, "package-lock.json"), "utf8"), ); -const safeVersion = "5.0.8"; +const safeVersion = "5.0.9"; const legacyRequire = /require\((["'])brace-expansion\1\)(?!\.expand)/g; const legacyImport = diff --git a/reports/release-manifest-v1.json b/reports/release-manifest-v1.json index 02d6ccbd7b..379091bd99 100644 --- a/reports/release-manifest-v1.json +++ b/reports/release-manifest-v1.json @@ -72,13 +72,13 @@ }, { "path": "backend/package-lock.json", - "sha256": "025dd00b9f216a2d3c27bd6d95cbae1f3b8a6e85d5a60d9833fc968624f7034e", + "sha256": "5883f47e70fb6e28c5db04c0a4b341bb21b3b2372c31370a767a961704d9359c", "sizeBytes": 203235 }, { "path": "backend/package.json", - "sha256": "51d850edb17c47a0f0f7a3254079579ea34a8b20d8260d2ba49e7bafc6278bca", - "sizeBytes": 1620 + "sha256": "db135dc85184779164869ebc1d2f86997a93f37087a7abe04fcb3dac0d6afde1", + "sizeBytes": 1694 }, { "path": "backend/scripts/restore-storage-exercise.mjs", @@ -357,13 +357,13 @@ }, { "path": "frontend/package-lock.json", - "sha256": "78c5149b7d30f1d3e39e545a995e8bf537a1368b302fd8ca452ddaffbe811fef", - "sizeBytes": 533845 + "sha256": "40618e553ad2a981be05db111ba9c7150910d28807325d29441ec9fe505aab6d", + "sizeBytes": 534050 }, { "path": "frontend/package.json", - "sha256": "22b09b9350f124db43a922da2add4519c2a6fad1bf5891fbc2a77683b8d614ab", - "sizeBytes": 2969 + "sha256": "e42439de3ef3f2102cb6145cac418d78f0e94328a3fbcf4769a977fa4e085911", + "sizeBytes": 2997 }, { "path": "frontend/src/app/components/projects/ProjectDocumentsView.tsx", @@ -627,13 +627,13 @@ }, { "path": "website/package-lock.json", - "sha256": "ecba6ff6eb960dc0c841e64c1752cd19ddbc573b0cce71739cce9411ad22184a", - "sizeBytes": 259462 + "sha256": "999aac2f2d545632172460dc2182f34425951a7cde2ad041dab9b8873bb9b8d7", + "sizeBytes": 259851 }, { "path": "website/package.json", - "sha256": "7cac4f02832a884ada383e460ed7b943b87a6dee86bf1713de6e6d77617eb40f", - "sizeBytes": 1621 + "sha256": "6d8b98afb2798f77766a225e21d7dc00554ea8b94371fc43c3f05a0715207669", + "sizeBytes": 1645 }, { "path": "website/app/site-config.ts", diff --git a/tests/baseline/ross-dependency-security-regressions.test.mjs b/tests/baseline/ross-dependency-security-regressions.test.mjs index 90e526e1be..b0e2e24641 100644 --- a/tests/baseline/ross-dependency-security-regressions.test.mjs +++ b/tests/baseline/ross-dependency-security-regressions.test.mjs @@ -13,7 +13,7 @@ test("every npm workspace resolves the patched brace-expansion release", () => { const packageJson = json(`${workspace}/package.json`); const lock = json(`${workspace}/package-lock.json`); - assert.equal(packageJson.overrides["brace-expansion"], "5.0.8"); + assert.equal(packageJson.overrides["brace-expansion"], "5.0.9"); assert.equal( packageJson.scripts.postinstall, "node scripts/patch-brace-expansion-compat.mjs", @@ -25,7 +25,7 @@ test("every npm workspace resolves the patched brace-expansion release", () => { }); assert.ok(bracePackages.length > 0); for (const [path, record] of bracePackages) { - assert.equal(record.version, "5.0.8", `${workspace}/${path}`); + assert.equal(record.version, "5.0.9", `${workspace}/${path}`); assert.doesNotMatch(String(record.resolved), /^file:/); } } @@ -40,7 +40,7 @@ test("legacy minimatch compatibility patching is deterministic and fail closed", ); assert.equal(frontendPatch, websitePatch); - assert.match(frontendPatch, /safeVersion = "5\.0\.8"/); + assert.match(frontendPatch, /safeVersion = "5\.0\.9"/); assert.match(frontendPatch, /require\\.*brace-expansion/); assert.match(frontendPatch, /import\\s\+/); assert.match(frontendPatch, /failed a basic glob match/); @@ -48,6 +48,35 @@ test("legacy minimatch compatibility patching is deterministic and fail closed", assert.match(frontendPatch, /No installed minimatch package was available/); }); +test("security-sensitive transitive dependencies stay on fixed releases", () => { + const workspaces = { + backend: { fastUri: "3.1.5", ipAddress: "10.4.0" }, + frontend: { undici: "7.29.0" }, + website: { fastUri: "3.1.5", undici: "7.29.0" }, + }; + + for (const [workspace, expected] of Object.entries(workspaces)) { + const packageJson = json(`${workspace}/package.json`); + const lock = json(`${workspace}/package-lock.json`); + const overrides = packageJson.overrides ?? {}; + + for (const [dependency, version] of Object.entries({ + ...(expected.fastUri ? { "fast-uri": expected.fastUri } : {}), + ...(expected.ipAddress ? { "ip-address": expected.ipAddress } : {}), + ...(expected.undici ? { undici: expected.undici } : {}), + })) { + assert.equal(overrides[dependency], version); + const resolved = Object.entries(lock.packages).filter(([path]) => + path === `node_modules/${dependency}` || + path.endsWith(`/node_modules/${dependency}`), + ); + assert.ok(resolved.length > 0, `${workspace} must lock ${dependency}`); + for (const [path, record] of resolved) + assert.equal(record.version, version, `${workspace}/${path}`); + } + } +}); + test("React server components and Next.js use their current patched releases", () => { const frontendPackage = json("frontend/package.json"); const websitePackage = json("website/package.json"); diff --git a/website/package-lock.json b/website/package-lock.json index 42d501526b..05f679f8ae 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -4081,9 +4081,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", - "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { @@ -5794,7 +5794,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.4", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "dev": true, "funding": [ { @@ -8760,7 +8762,9 @@ } }, "node_modules/undici": { - "version": "7.28.0", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", "dev": true, "license": "MIT", "engines": { diff --git a/website/package.json b/website/package.json index 3e0fa239ac..89f9b024ac 100644 --- a/website/package.json +++ b/website/package.json @@ -42,8 +42,9 @@ "wrangler": "4.114.0" }, "overrides": { - "brace-expansion": "5.0.8", - "fast-uri": "3.1.4", + "brace-expansion": "5.0.9", + "fast-uri": "3.1.5", + "undici": "7.29.0", "postcss": "8.5.22", "sharp": "0.35.3" }, diff --git a/website/scripts/patch-brace-expansion-compat.mjs b/website/scripts/patch-brace-expansion-compat.mjs index 9f395bd611..dcb540deab 100644 --- a/website/scripts/patch-brace-expansion-compat.mjs +++ b/website/scripts/patch-brace-expansion-compat.mjs @@ -15,7 +15,7 @@ const root = resolve(import.meta.dirname, ".."); const lock = JSON.parse( readFileSync(resolve(root, "package-lock.json"), "utf8"), ); -const safeVersion = "5.0.8"; +const safeVersion = "5.0.9"; const legacyRequire = /require\((["'])brace-expansion\1\)(?!\.expand)/g; const legacyImport =