From 4db7689b8a6f6916e412fd94b105ad66529ad036 Mon Sep 17 00:00:00 2001 From: zodyp Date: Sat, 19 Sep 2026 13:46:14 -0300 Subject: [PATCH 1/2] fix(deps): clear the js-yaml advisory from the Electron chain (R-10) GHSA-2883-xcg3-v3hh (high, CVSS 7.5) reached the Electron app's production tree through electron-updater 6.8.9 -> js-yaml 4.3.1, the update-check chain. It was the last high advisory in a shipped production tree and the only record still carried as an accepted residual. Lockfile-only fix: `npm update js-yaml --package-lock-only --ignore-scripts` moved js-yaml 4.3.1 -> 4.3.2, inside both electron-updater's declared ^4.1.0 and the existing ^4.2.0 override in electron/package.json. No package.json change and no new override were needed. node_modules was not touched. electron prod before: high 1, total 1 -> after: 0 across every severity electron full after: 0 across every severity (the dev-only app-builder-lib / builder-util / dmg-builder copies dedupe onto the same hoisted entry, so one bump cleared them too) root prod 0 before and after - untouched by this change The lockfile diff is five lines: three for js-yaml (version, resolved, integrity) and two where npm synchronised the lockfile's own version field from a stale 3.8.51 to the 3.8.54 already declared in electron/package.json. No other package changed version. Docs updated to match: R-10 is marked fixed in the vulnerability register (summary row, detail section, proposed-PR item) with a new Electron re-measurement section, and EVOLUTION_STATUS's Phase 10 table, risks table and known-limits list no longer describe it as an accepted residual. Verified: check:lockfile OK; both commands behind audit:electron exit 0; check-doc-links, check-fabricated-docs, check-docs-frontmatter, check-docs-sync and check-changelog-integrity all pass. A full electron-builder packaging run was not executed - it needs the Electron binaries and a signing environment this worktree does not have; the packaging config was verified to parse and to be unchanged. Co-Authored-By: Claude Opus 5 --- docs/EVOLUTION_STATUS.md | 22 +++++-- docs/security/VULNERABILITY_REGISTER.md | 81 ++++++++++++++++++++----- electron/package-lock.json | 10 +-- 3 files changed, 88 insertions(+), 25 deletions(-) diff --git a/docs/EVOLUTION_STATUS.md b/docs/EVOLUTION_STATUS.md index 8adf1b79140..5df251ff86a 100644 --- a/docs/EVOLUTION_STATUS.md +++ b/docs/EVOLUTION_STATUS.md @@ -198,7 +198,11 @@ images are digest-pinned. Measured on the release tree with `npm audit --omit=de | Tree | info | low | moderate | high | critical | | ------------------- | ---- | --- | -------- | ----- | -------- | | Root production | 0 | 0 | 0 | **0** | **0** | -| Electron production | 0 | 0 | 0 | **1** | **0** | +| Electron production | 0 | 0 | 0 | **0** | **0** | + +Re-measured on 2026-09-19 after the `js-yaml` fix below. The Electron tree is also clean in the +full run that includes dev dependencies (`npm audit --package-lock-only`: 0 across every +severity). The verification round caught this claim being stale: a second, higher advisory on `adm-zip` (GHSA-7q85-xj36-vmfc, high, fixed in 0.6.1) had appeared in the root production tree through the @@ -206,9 +210,13 @@ optional `@huggingface/transformers` → `onnxruntime-node` chain, while the reg was none. It was fixed rather than re-documented — a lockfile-only bump to 0.6.1 inside the existing `^0.6.0` override, a three-line diff that took root production from `high: 1, moderate: 2` to zero. -The remaining `high` is accepted as residual: `js-yaml` 4.3.1, register id **R-10**, reachable only -from the Electron shell's update-check chain. It is not in the container image, the npm package or -the server runtime, and clearing it needs an Electron lockfile refresh that is out of scope here. +The last remaining `high` was then cleared the same way rather than carried: `js-yaml` 4.3.1, register +id **R-10**, reachable only from the Electron shell's update-check chain (`electron-updater` 6.8.9 → +`js-yaml`), never in the container image, the npm package or the server runtime. A lockfile-only bump +to 4.3.2 inside the existing `^4.2.0` override took Electron production from `high: 1` to zero, and +the shared hoisted copy meant it cleared the dev-tree `electron-builder` entries too. `package.json` +is unchanged; the diff is five lines of `electron/package-lock.json`. **No advisory is accepted as +residual in either shipped production tree.** ## Phase 11: documentation @@ -265,7 +273,7 @@ have been irreversible or contract-breaking in a patch release. | The in-memory decision store grows under a burst of wide candidate pools | Low | Memory pressure on the server process | Bounded by count, by a 32 MB byte budget and by a 30-minute TTL; candidates are compacted before storage | | An operator enables SLO webhook alerts and gets paged by a breach that is really an idle provider | Low | Alert fatigue | An idle open breaker reports `insufficient_data` instead of breaching; alert state resets when alerting is toggled | | A routing decision id is guessed and read by another caller | Low | Disclosure of routing metadata (never prompts or credentials) | Management auth on the lookup route; identical `404` for unknown and malformed ids | -| The Electron `js-yaml` advisory (R-10) is exploited | Low | Build-chain only; no server or dashboard exposure | Recorded in the vulnerability register; a lockfile-only refresh is planned | +| The Electron `js-yaml` advisory (R-10) is exploited | Closed | Build-chain only; no server or dashboard exposure | **Fixed** 2026-09-19: lockfile-only bump to `js-yaml` 4.3.2; Electron production audit is now clean | | The 151 OpenAPI-covered routes without a contract test drift from the served contract | Medium | Documentation and SDKs disagree with the server | The governance baseline tracks them and cannot grow; the SDK drift test covers the documented surface | | A gate or test run without isolated `DATA_DIR`/`HOME` touches a developer's real database | Medium | Unintended migration on a production install | Every command in this release exported isolated `DATA_DIR`, `HOME`, `USERPROFILE` and `APPDATA`; `tests/_setup/isolateDataDir.ts` enforces it in the test runner | @@ -274,7 +282,9 @@ have been irreversible or contract-breaking in a patch release. - The **workspace and budget hierarchy** is designed but not implemented (Phase 8 ADR). - **151 routes** are covered by OpenAPI but have no contract test referencing them yet; the governance baseline tracks them. -- The **`js-yaml` R-10** advisory in the Electron chain is accepted as residual. +- ~~The **`js-yaml` R-10** advisory in the Electron chain is accepted as residual.~~ Fixed + 2026-09-19 — `js-yaml` 4.3.2, lockfile only. No advisory is accepted as residual in either + shipped production tree. - A live **latency budget** is not enforced per candidate; the contract documents exactly what live traffic does enforce, and the remaining work depends on decomposing `open-sse/services/combo.ts`. - Accessibility was gated on login, dashboard, providers and settings; combos, logs and onboarding diff --git a/docs/security/VULNERABILITY_REGISTER.md b/docs/security/VULNERABILITY_REGISTER.md index 3cb47fd81b7..16ca3269852 100644 --- a/docs/security/VULNERABILITY_REGISTER.md +++ b/docs/security/VULNERABILITY_REGISTER.md @@ -42,7 +42,9 @@ Result, as measured on 2026-09-14: this run and made the same tree report `high: 1` without any dependency changing. - Root dev-only: 4 high advisories (2 × extract-zip, js-yaml, smol-toml), 0 critical. - Electron app (`electron/package-lock.json`): 1 high advisory in a production dependency - (R-10). + (R-10). **This statement expired.** R-10 was fixed on 2026-09-19 — see the + [Electron re-measurement](#electron-re-measurement--2026-09-19); that tree now reports no + advisory of any severity. ## Re-measurement — 2026-09-19 @@ -61,7 +63,9 @@ Result, as measured on 2026-09-14: **Current result: the root production tree reports no advisory of any severity.** Both adm-zip records (R-01 and R-11) are closed by the fix; the remaining 7 entries in the full run -are the dev-only records R-02 … R-09. The Electron app lockfile is unchanged (R-10 still open). +are the dev-only records R-02 … R-09. The Electron app lockfile was still unchanged at this +point (R-10 open); it was fixed later the same day — see the +[Electron re-measurement](#electron-re-measurement--2026-09-19). The fix is item 2 of the [Proposed dependency PR](#proposed-dependency-pr-not-applied), applied as a lockfile-only change: `npm update adm-zip --package-lock-only --ignore-scripts` moved @@ -71,6 +75,49 @@ integrity). `node_modules` was not touched. Verified afterwards: `tests/unit/onnxruntime-single-copy.test.ts` (2/2 pass, the transformers/onnxruntime version pair is intact) and `npm run check:lockfile` (OK). +## Electron re-measurement — 2026-09-19 + +- Toolchain: Node v24.16.0, npm 11.13.0. Electron lockfile: 285 packages audited. +- Trigger: R-10 was the last high advisory left in a shipped production tree, and it was the + only record still described as an accepted residual. + +| Run | Command | Critical | High | Moderate | Low | Total | +| ------------------------------ | --------------------------------------------------- | -------- | ----- | -------- | --- | ----- | +| electron prod (before the fix) | `npm audit --omit=dev --package-lock-only` | 0 | **1** | 0 | 0 | 1 | +| electron prod (after the fix) | `npm audit --omit=dev --package-lock-only` | 0 | 0 | 0 | 0 | 0 | +| electron full (after the fix) | `npm audit --package-lock-only` | 0 | 0 | 0 | 0 | 0 | +| root prod (unchanged by this) | `npm audit --omit=dev --package-lock-only` | 0 | 0 | 0 | 0 | 0 | + +**Current result: both shipped production trees report no advisory of any severity, and the +Electron tree is clean in the full run too** — the dev-only `app-builder-lib`, `builder-util` +and `dmg-builder` copies deduplicate onto the same hoisted `js-yaml`, so the single bump +cleared them as well. + +The fix is item 1 of the [Proposed dependency PR](#proposed-dependency-pr-not-applied), applied +as a lockfile-only change: `npm update js-yaml --package-lock-only --ignore-scripts` moved +`js-yaml` 4.3.1 → 4.3.2 inside the existing Electron override `^4.2.0` (and inside +`electron-updater`'s declared `^4.1.0`). `electron/package.json` is unchanged — the override +already permitted the fixed version, so no new `overrides` entry was needed. `node_modules` was +not touched. + +The diff is five lines of `electron/package-lock.json`: three for `js-yaml` (version, resolved, +integrity) and two where npm synchronised the lockfile's own `version` field from the stale +`3.8.51` to the `3.8.54` already declared in `electron/package.json`. No other package changed +version. + +Verified afterwards: `npm run check:lockfile` (OK) and the two commands behind +`audit:electron` — `npm --prefix electron audit --audit-level=critical` and +`--audit-level=high` — both exit 0, so the non-blocking high-severity warning that this script +used to print is gone. The `audit:electron` script itself was not run end to end on this +machine: its `(cmd || echo)` shell form is POSIX syntax that cmd.exe rejects before npm audit +runs, which is a pre-existing Windows-only limitation of the script and unrelated to this +change. + +A full `electron-builder` packaging run was **not** executed here — it needs a download of the +Electron binaries and a code-signing environment this worktree does not have. What was checked +instead: `electron/package.json` parses, its `build` block is byte-for-byte unchanged by this +commit, and the only file this commit touches under `electron/` is `package-lock.json`. + ## Summary | ID | Advisory | Package | npm severity | Tree | Installed | First fixed | Action | @@ -84,7 +131,7 @@ pair is intact) and `npm run check:lockfile` (OK). | R-07 | GHSA-8cw4-87c7-c6xx | csv-parse | moderate | root dev | 7.0.1 | 7.0.2 | Lockfile refresh proposed | | R-08 | GHSA-6w3j-5fw6-r9vr | joi | low | root dev | 18.2.3 | 18.2.5 | Lockfile refresh proposed | | R-09 | GHSA-gg4h-3hg2-grpc | joi | low | root dev | 18.2.3 | 18.2.4 | Lockfile refresh proposed | -| R-10 | GHSA-2883-xcg3-v3hh | js-yaml | high | electron app production | 4.3.1 | 4.3.2 | Lockfile refresh proposed (priority) | +| R-10 | GHSA-2883-xcg3-v3hh | js-yaml | high | electron app production | 4.3.2 | 4.3.2 | **Fixed** 2026-09-19 (lockfile only) | | R-11 | GHSA-7q85-xj36-vmfc | adm-zip | high | root production (optional) | 0.6.1 | 0.6.1 | **Fixed** 2026-09-19 (lockfile only) | Propagation-only entries (no advisory of their own): `@huggingface/transformers` and @@ -311,15 +358,20 @@ existing ranges and overrides, with no `package.json` edit. See ### R-10 — js-yaml: merge-key CPU exhaustion (Electron app production tree) -- **Package:** `js-yaml` 4.3.1 (`electron/package-lock.json`, `node_modules/js-yaml`, not - marked dev). +**Status: fixed 2026-09-19** (lockfile only). `js-yaml` 4.3.1 → 4.3.2 in +`electron/package-lock.json`. The Electron production tree now reports no advisory of any +severity. Details below describe the advisory as it stood before the fix. + +- **Package:** `js-yaml` 4.3.2 (`electron/package-lock.json`, `node_modules/js-yaml`, not + marked dev). Was 4.3.1 before the fix. - **Advisory:** GHSA-2883-xcg3-v3hh / CVE-2026-84375 — high, CVSS 7.5, CWE-400/CWE-407, published 2026-09-08. This is the same advisory as R-04, recorded separately because it ships in a different artifact. - **Dependency path:** Electron app dependency `electron-updater` 6.8.9 (declared - `^6.8.9` in `electron/package.json`; it declares `js-yaml ^4.1.0`) → `js-yaml` 4.3.1. The + `^6.8.9` in `electron/package.json`; it declares `js-yaml ^4.1.0`) → `js-yaml`. The build-only packages `app-builder-lib`, `builder-util` and `dmg-builder` 26.15.3 (dev) - resolve the same copy. + resolve the same copy, so the single hoisted entry served both trees and one bump cleared + both. - **Affected versions:** `>=4.0.0 <4.3.2`. - **Fixed version:** 4.3.2. - **Real exploitability in OmniRoute:** low. @@ -332,19 +384,20 @@ existing ranges and overrides, with no `package.json` edit. See - This does not affect the npm package or the Docker image. - **Impact if exploited:** the Electron main process hangs or spikes CPU during an update check, a denial of service of the desktop app. -- **Action taken:** none in code. Proposed: refresh the `electron/package-lock.json` entry to - 4.3.2 (allowed by `^4.1.0`); this is the only high advisory in a shipped production tree. -- **Justification:** exploitation needs control of the release feed. The fix is a lockfile - change in a separate lockfile, out of scope for this phase. `audit:electron` blocks only on - critical, so it reports this as a warning. +- **Action taken:** fixed on 2026-09-19. `npm update js-yaml --package-lock-only + --ignore-scripts` refreshed the `electron/package-lock.json` entry to 4.3.2, allowed by both + `electron-updater`'s declared `^4.1.0` and the existing `^4.2.0` override in + `electron/package.json`. No `package.json` change and no new override were needed. + `audit:electron` no longer emits its non-blocking high-severity warning. ## Proposed dependency PR (not applied) This should be a dedicated PR that changes only `package-lock.json` and `electron/package-lock.json`, with no mass upgrade: -1. `electron/package-lock.json`: `js-yaml` 4.3.1 → 4.3.2 (R-10), within `^4.1.0`. Do this - first: it is the only high advisory in a shipped production tree. +1. ~~`electron/package-lock.json`: `js-yaml` 4.3.1 → 4.3.2 (R-10), within `^4.1.0`.~~ + **Applied 2026-09-19** — lockfile only, via `npm update js-yaml --package-lock-only + --ignore-scripts`. It was the last high advisory in a shipped production tree. 2. ~~`adm-zip` 0.6.0 → 0.6.1 (R-01), within the root override `^0.6.0`.~~ **Applied 2026-09-19** — lockfile only, via `npm update adm-zip --package-lock-only`. It also closes R-11, the high advisory that appeared later on the same package. diff --git a/electron/package-lock.json b/electron/package-lock.json index 3a09058e08a..02dce083982 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute-desktop", - "version": "3.8.51", + "version": "3.8.54", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute-desktop", - "version": "3.8.51", + "version": "3.8.54", "license": "MIT", "dependencies": { "electron-updater": "^6.8.9" @@ -2234,9 +2234,9 @@ } }, "node_modules/js-yaml": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", - "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "funding": [ { "type": "github", From 417504442c7f91004405d810611b8577b7bdd376 Mon Sep 17 00:00:00 2001 From: zodyp Date: Sat, 19 Sep 2026 13:52:36 -0300 Subject: [PATCH 2/2] docs(security): the dependency PR heading no longer says "not applied" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Items 1 and 2 of that section are both applied now — adm-zip 0.6.1 in PR #42 and js-yaml 4.3.2 in this one — so a heading reading "Proposed dependency PR (not applied)" states the opposite of what the section records. Renaming it moves the anchor, which is why it was left alone. But all three references live inside this same file, so there was nothing external to break: the heading and its three links are updated together. check-doc-links exit 0 — 172 docs, 1044 internal links, none broken Co-Authored-By: Claude Opus 5 --- docs/security/VULNERABILITY_REGISTER.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/security/VULNERABILITY_REGISTER.md b/docs/security/VULNERABILITY_REGISTER.md index 16ca3269852..5972696bb12 100644 --- a/docs/security/VULNERABILITY_REGISTER.md +++ b/docs/security/VULNERABILITY_REGISTER.md @@ -67,7 +67,7 @@ are the dev-only records R-02 … R-09. The Electron app lockfile was still unch point (R-10 open); it was fixed later the same day — see the [Electron re-measurement](#electron-re-measurement--2026-09-19). -The fix is item 2 of the [Proposed dependency PR](#proposed-dependency-pr-not-applied), applied +The fix is item 2 of the [dependency PR items](#dependency-pr-items), applied as a lockfile-only change: `npm update adm-zip --package-lock-only --ignore-scripts` moved `adm-zip` 0.6.0 → 0.6.1 inside the existing root override `^0.6.0`. `package.json` is unchanged and the whole diff is three lines of `package-lock.json` (version, resolved, @@ -81,19 +81,19 @@ pair is intact) and `npm run check:lockfile` (OK). - Trigger: R-10 was the last high advisory left in a shipped production tree, and it was the only record still described as an accepted residual. -| Run | Command | Critical | High | Moderate | Low | Total | -| ------------------------------ | --------------------------------------------------- | -------- | ----- | -------- | --- | ----- | -| electron prod (before the fix) | `npm audit --omit=dev --package-lock-only` | 0 | **1** | 0 | 0 | 1 | -| electron prod (after the fix) | `npm audit --omit=dev --package-lock-only` | 0 | 0 | 0 | 0 | 0 | -| electron full (after the fix) | `npm audit --package-lock-only` | 0 | 0 | 0 | 0 | 0 | -| root prod (unchanged by this) | `npm audit --omit=dev --package-lock-only` | 0 | 0 | 0 | 0 | 0 | +| Run | Command | Critical | High | Moderate | Low | Total | +| ------------------------------ | ------------------------------------------ | -------- | ----- | -------- | --- | ----- | +| electron prod (before the fix) | `npm audit --omit=dev --package-lock-only` | 0 | **1** | 0 | 0 | 1 | +| electron prod (after the fix) | `npm audit --omit=dev --package-lock-only` | 0 | 0 | 0 | 0 | 0 | +| electron full (after the fix) | `npm audit --package-lock-only` | 0 | 0 | 0 | 0 | 0 | +| root prod (unchanged by this) | `npm audit --omit=dev --package-lock-only` | 0 | 0 | 0 | 0 | 0 | **Current result: both shipped production trees report no advisory of any severity, and the Electron tree is clean in the full run too** — the dev-only `app-builder-lib`, `builder-util` and `dmg-builder` copies deduplicate onto the same hoisted `js-yaml`, so the single bump cleared them as well. -The fix is item 1 of the [Proposed dependency PR](#proposed-dependency-pr-not-applied), applied +The fix is item 1 of the [dependency PR items](#dependency-pr-items), applied as a lockfile-only change: `npm update js-yaml --package-lock-only --ignore-scripts` moved `js-yaml` 4.3.1 → 4.3.2 inside the existing Electron override `^4.2.0` (and inside `electron-updater`'s declared `^4.1.0`). `electron/package.json` is unchanged — the override @@ -146,7 +146,7 @@ or `electron/package-lock.json`). This phase runs against a shared `node_modules not regenerate lockfiles or mix dependency upgrades with other changes. The declared ranges in the lockfiles show that each fixable record resolves by refreshing lock entries within the existing ranges and overrides, with no `package.json` edit. See -[Proposed dependency PR](#proposed-dependency-pr-not-applied). +[dependency PR items](#dependency-pr-items). ## Records @@ -385,19 +385,19 @@ severity. Details below describe the advisory as it stood before the fix. - **Impact if exploited:** the Electron main process hangs or spikes CPU during an update check, a denial of service of the desktop app. - **Action taken:** fixed on 2026-09-19. `npm update js-yaml --package-lock-only - --ignore-scripts` refreshed the `electron/package-lock.json` entry to 4.3.2, allowed by both +--ignore-scripts` refreshed the `electron/package-lock.json` entry to 4.3.2, allowed by both `electron-updater`'s declared `^4.1.0` and the existing `^4.2.0` override in `electron/package.json`. No `package.json` change and no new override were needed. `audit:electron` no longer emits its non-blocking high-severity warning. -## Proposed dependency PR (not applied) +## Dependency PR items This should be a dedicated PR that changes only `package-lock.json` and `electron/package-lock.json`, with no mass upgrade: 1. ~~`electron/package-lock.json`: `js-yaml` 4.3.1 → 4.3.2 (R-10), within `^4.1.0`.~~ **Applied 2026-09-19** — lockfile only, via `npm update js-yaml --package-lock-only - --ignore-scripts`. It was the last high advisory in a shipped production tree. +--ignore-scripts`. It was the last high advisory in a shipped production tree. 2. ~~`adm-zip` 0.6.0 → 0.6.1 (R-01), within the root override `^0.6.0`.~~ **Applied 2026-09-19** — lockfile only, via `npm update adm-zip --package-lock-only`. It also closes R-11, the high advisory that appeared later on the same package.