Files
iptvnator/docs/architecture/dependency-security-overrides.md
T
4grayandClaude Opus 5 d2316fafe9 fix(deps): patch transitive runtime CVEs via pnpm overrides
Closes 13 runtime-scope Dependabot advisories that Dependabot itself
cannot fix: the vulnerable packages are all transitive, so the bot has no
lever until each parent publishes a release widening its own pin.

Overrides added (pinned-source form, matching existing convention):

- @xmldom/xmldom 0.8.11 -> 0.8.13  (5 high) via video.js -> mpd-parser
- fast-uri       3.1.0  -> 3.1.4   (4 high) via electron-conf -> ajv
- js-yaml        4.1.1  -> 4.3.0   (2)      via electron-updater
- form-data      4.0.5  -> 4.0.6   (1 high) via axios
- ajv            8.17.1 -> 8.18.0  (1)      via electron-conf

Every target stays inside its parent's declared semver range. For xmldom,
fast-uri and js-yaml the newest published version is *outside* that range
(0.9.x / 4.x / 5.x), so "latest" would have broken them - the new doc
records that constraint.

Deliberately excluded:

- axios and uuid are direct deps already covered by open Dependabot PRs
  (#1251 bumps axios 1.16.0 -> 1.18.1; #1252 covers uuid). Hand-bumping
  them here would only conflict on the lockfile.
- undici (7 advisories) is labelled runtime scope but every path to it is
  build tooling - electron -> @electron/get, @angular/build, and
  @module-federation/dts-plugin. It is not in the packaged app.

Note on reachability: xmldom arrives via video.js -> VHS -> mpd-parser,
but the app routes every .mpd to Shaka, which uses its own DASH parser.
The code ships but is not on the playback path, so this is defence in
depth rather than closing a live hole. The genuinely reachable one is
js-yaml, which electron-updater uses to parse latest.yml from releases.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 22:25:38 +02:00

2.9 KiB

Dependency Security Overrides

How transitive CVEs are patched in this repo, and the constraint that makes "just bump to latest" the wrong move.

Why overrides exist

Dependabot can only bump packages we declare ourselves. When the vulnerable package is transitive — pulled in by video.js, electron-updater, electron-conf, axios — the bot has no lever: it would have to wait for the parent to publish a release that widens its own pin. Until then the alert stays open regardless of how many bot PRs land.

pnpm.overrides in the root package.json is that lever. Every entry uses the pinned-source form so an override only rewrites the exact resolution it was written for, and goes stale visibly instead of silently re-targeting a future version:

"@xmldom/xmldom@0.8.11": "0.8.13"

The semver ceiling

An override must stay inside the range its parent declares. pnpm applies overrides without re-checking the parent's range, so an out-of-range target installs cleanly and then fails at runtime or under load, not at install time.

For three of the five current security overrides, the newest published version is outside the parent's range. Taking "latest" would break them:

Override Pinned to Parent range Latest on npm
@xmldom/xmldom 0.8.13 mpd-parser ^0.8.3, plist ^0.8.8 0.9.x ❌
fast-uri 3.1.4 ajv ^3.0.1 4.x ❌
js-yaml 4.3.0 electron-updater ^4.1.0 5.x ❌
form-data 4.0.6 axios ^4.0.5 4.0.6 ✅
ajv 8.18.0 electron-conf ^8.13.0 8.20.0 ✅

Before changing any of these, check the parent's declared range first:

npm view <parent>@<version> dependencies --json

Verifying an override actually applied

pnpm leaves the superseded package block in pnpm-lock.yaml even when nothing resolves to it any more, so grepping for the old version is misleading — it will still be there. Check the dependents instead, or resolve the real path on disk:

node -e "console.log(require('./node_modules/.pnpm/mpd-parser@1.3.1/node_modules/@xmldom/xmldom/package.json').version)"

What is deliberately not overridden

undici carries open alerts flagged runtime scope, but every path to it is build tooling — electron → @electron/get, @angular/build, and @module-federation/dts-plugin. It is not in the packaged app. The runtime label is a Dependabot classification artifact, not a shipped-code claim. Bumping it inside the Angular/Nx toolchain risks the build for no runtime benefit.

When triaging, confirm scope from the dependency graph rather than trusting the alert's scope field.