From cb508c5d165a77d82f252ee4fc3ba861603c5177 Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 5 Aug 2026 07:48:23 +0200 Subject: [PATCH] brace-expansion override ^5.0.8 -> ^5.0.9 (GHSA-rgw5-rvv9-x895, DoS). 5.0.8's maxLength cap was applied in combine(), where output is merged, but not to the two arrays built before it runs: comma alternatives each got their own full allowance and were concatenated with no running total, and padded sequences never consulted maxLength at all. So a ~25 KB pattern still OOMs the process -- fatally, past the reach of try/catch -- and a ~400 KB one blocks the event loop for over two minutes. 5.0.9 bounds both as they are built. Dev-only and transitive here: it reaches us as eslint -> minimatch@5 -> brace-expansion, the only input it sees is our own lint globs, and it is not in the shipped bundle. The ci.yml audit gate runs --omit=dev, so this never would have failed CI; it surfaced through Dependabot. The overrides floor is bumped alongside the lockfile so a clean install can't resolve back to the vulnerable 5.0.8. --- CHANGELOG.md | 2 +- frontend/package-lock.json | 6 +++--- frontend/package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3dc1ebcb..a52d92e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,7 +107,7 @@ All notable changes to Bambuddy will be documented in this file. - **Force color match dispatched a print onto the wrong PLA variant — Matte jobs went to Basic and Silk printers alike, and the wrong AMS slot on a printer holding two same-colour variants (#2650, reporter @MartinNYHC)** — With **Force color match** on, a job sliced for **White PLA Matte** was dispatched to every printer that had *any* white PLA loaded — the ones holding White PLA **Basic** and White PLA **Silk+** included — so a matte model came out glossy on the wrong machine. **Root cause.** Bambu's MQTT status reports every PLA sub-variant as `tray_type == "PLA"`; the Basic/Matte/Silk distinction is carried only in `tray_info_idx` (`GFA00` = Basic, `GFA01` = Matte, `GFA06` = Silk, …), which the 3MF's `slice_info.config` also records per filament. Three places dropped it: the Virtual-Printer queue built each force override as `{slot_id, type, color, force_color_match}` without the parsed `tray_info_idx`; the scheduler's eligibility check (`_get_missing_force_color_slots`) compared loaded trays on `(type, colour)` only — so `(PLA, #FFFFFF)` matched Basic, Matte and Silk indiscriminately and all three printers looked eligible; and the AMS slot mapper cleared `tray_info_idx` when applying the override, so even on the correct printer it could pick a different-variant tray of the same colour. **Fix.** The force override now carries the 3MF's `tray_info_idx`; a slot counts as satisfied only when a loaded tray matches type **and** colour **and** the variant (identical `tray_info_idx`, *or* either side lacks one); and the slot mapper now keeps the variant for force-colour overrides so it pins the matching tray. A blank idx on either side (custom/third-party spools report none, and older 3MFs carry none) falls back to the historical type+colour behaviour, so those setups are unaffected, and a manual filament *swap* (a preference override) still clears the idx so it matches the swapped-in spool rather than the old one. A job sliced for GFA01 now goes only to a printer with GFA01 loaded, and lands on that printer's GFA01 tray. The printer-card queue-compatibility hint (which printers show a pending job as runnable) now applies the same variant rule. Covered by scheduler tests (Matte requirement rejects Basic/Silk, accepts Matte, blank loaded idx falls back, requirement without an idx unchanged; the mapper pins the GFA01 tray over a same-colour GFA00 on both the 3MF and no-3MF paths; a preference swap still matches by colour), a Virtual-Printer test asserting the override carries `tray_info_idx`, and frontend tests for the variant-aware queue hint (rejects other variants, accepts the match, blank-idx and no-variant-data fall back). ### Security -- **Patched two build-time frontend dependencies flagged by `npm audit` (GHSA-r28c-9q8g-f849, GHSA-mh99-v99m-4gvg)** — `postcss` 8.5.15 → 8.5.23 fixes a path traversal in its source-map auto-loader (`sourceMappingURL`) that could disclose arbitrary `.map` files, and `brace-expansion` (pulled in transitively by `eslint` via `minimatch`) is bumped through the existing `overrides` block (`^5.0.7` → `^5.0.8`) for a denial-of-service via unbounded expansion. Both are build/lint-time tooling only — neither is part of the shipped app, so no running Bambuddy install was exposed. `postcss` moved within its existing range; `brace-expansion` needed the pin because `npm audit fix` can't lift `eslint` to the patched transitive on its own. +- **Patched two build-time frontend dependencies flagged by `npm audit` (GHSA-r28c-9q8g-f849, GHSA-mh99-v99m-4gvg, GHSA-rgw5-rvv9-x895)** — `postcss` 8.5.15 → 8.5.23 fixes a path traversal in its source-map auto-loader (`sourceMappingURL`) that could disclose arbitrary `.map` files, and `brace-expansion` (pulled in transitively by `eslint` via `minimatch`) is bumped through the existing `overrides` block (`^5.0.7` → `^5.0.9`) for a denial-of-service via unbounded expansion. The first `brace-expansion` advisory was answered in 5.0.8 by capping the length of the combined result, but that cap covered only the accumulator the results are merged into and not the two intermediate arrays that feed it — so a small brace pattern could still exhaust the heap, fatally and beyond the reach of a `try`/`catch`, or stall the event loop for minutes. 5.0.9 bounds both arrays as they are built. Both packages are build/lint-time tooling only — neither is part of the shipped app, so no running Bambuddy install was exposed. `postcss` moved within its existing range; `brace-expansion` needed the pin because `npm audit fix` can't lift `eslint` to the patched transitive on its own. - **Pinned `react-router` to its most-patched 7.x (7.18.1) and documented the one remaining, unreachable advisory (GHSA-qwww-vcr4-c8h2)** — Staying current on the 7.x line matters: 7.18.1 clears 14 advisories that older 7.x releases carry, several reachable in a browser SPA (open-redirect XSS in ``/`useNavigate`, route-matching DoS). The single advisory that still flags 7.18.1 — a CSRF bypass — applies only to React Router's **RSC mode**, which requires the server runtime (`@react-router/server`, not installed); Bambuddy is a Vite SPA using `BrowserRouter`, so the vulnerable path is unreachable. There is no non-major fix (the patch landed only in the 8.3.0 major, and `react-router-dom` has no 8.x — adopting it would mean migrating every import to `react-router` plus a React peer bump), so `react-router`/`react-router-dom` are pinned to 7.18.1 and the finding is carried as a documented, fail-closed exception in the CI audit gate: a *different* react-router advisory still fails CI, and the exemption is dropped automatically the moment a non-major fix ships. `npm audit fix --force` is deliberately avoided — its suggested "fix" is a downgrade to 7.11.0, which reintroduces those 14 advisories. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c949c7e1e..40d1cd8b1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3173,9 +3173,9 @@ } }, "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, "dependencies": { "balanced-match": "^4.0.2" diff --git a/frontend/package.json b/frontend/package.json index 9f40df21d..1f0e22d9f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,7 +48,7 @@ }, "overrides": { "minimatch": "^10.2.1", - "brace-expansion": "^5.0.8", + "brace-expansion": "^5.0.9", "js-yaml": "^4.3.0", "react-router": "7.18.1" },