From 78228e4d3b0526875705047032dc0cf8174cf12c Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Sun, 16 Aug 2026 12:00:00 +0000 Subject: [PATCH] =?UTF-8?q?docs(issues):=20#0055=20=E2=80=94=20the=20@sorb?= =?UTF-8?q?=20scope=20is=20pinned=20nowhere=20but=20the=20lockfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ThreadNet-Web resolves @sorb/threadnet-call-embedded from rohana only because pnpm-lock.yaml pins the full tarball URL and CI installs frozen. There is no .npmrc anywhere, so the moment someone bumps the version, pnpm reaches for registry.npmjs.org instead. Hit while bumping to .8 for #0054. Today that fails loudly with a 404 — but only because the name happens to be unregistered on public npm. The protection is a coincidence, not a control: register that name and the same command resolves successfully against a stranger's package, in the one moment where a fresh download looks expected. Documenting it is explicitly not the fix here; the checked-in .npmrc is, because it removes the wrong path rather than warning about it. Co-Authored-By: Claude Opus 4.8 --- STATUS.md | 5 +- ...0055-npm-scope-aufloesung-threadnet-web.md | 95 +++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 docs/issues/0055-npm-scope-aufloesung-threadnet-web.md diff --git a/STATUS.md b/STATUS.md index b10b56d..b29a1e8 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,9 +2,9 @@ -## Issues (21 open, 27 closed) +## Issues (22 open, 27 closed) -Verteilung: M1 5 · M2 12 · M4 3 · M5 1 +Verteilung: M1 5 · M2 13 · M4 3 · M5 1 | Issue | Status | Meilenstein | Priorität | Title | |---|---|---|---|---| @@ -29,6 +29,7 @@ Verteilung: M1 5 · M2 12 · M4 3 · M5 1 | [0051](docs/issues/0051-cve-remediation-pass.md) | open | M5 | high | CVE-Remediation-Pass: Schwachstellen-Report abarbeiten | | [0053](docs/issues/0053-historien-durchgang-nicht-kanonische-commits.md) | open | M2 | low | Historien-Durchgang: acht nicht-kanonische Commits mitziehen | | [0054](docs/issues/0054-ki-geraeuschunterdrueckung-element-call.md) | open | M4 | medium | Tastaturgeräusche in Calls: quelloffene KI-Geräuschunterdrückung im Client prüfen | +| [0055](docs/issues/0055-npm-scope-aufloesung-threadnet-web.md) | open | M2 | medium | Issue-0055: `@sorb`-Scope in ThreadNet-Web ist nirgends auf rohana festgelegt | ## Active design docs (0) diff --git a/docs/issues/0055-npm-scope-aufloesung-threadnet-web.md b/docs/issues/0055-npm-scope-aufloesung-threadnet-web.md new file mode 100644 index 0000000..3bb9460 --- /dev/null +++ b/docs/issues/0055-npm-scope-aufloesung-threadnet-web.md @@ -0,0 +1,95 @@ +--- +type: issue +id: "0055" +status: open +created: 2026-08-16 +milestone: M2 +priority: medium +area: security +related: + - "docs/issues/0054-ki-geraeuschunterdrueckung-element-call.md" + - "docs/adr/0018-ki-geraeuschunterdrueckung-clientseitig-opt-in.md" + - "docs/adr/0001-gitlab-kanonisch-push-mirror.md" +--- + +# Issue-0055: `@sorb`-Scope in ThreadNet-Web ist nirgends auf rohana festgelegt + +## Problem / Motivation + +`ThreadNet-Web` bezieht `@sorb/threadnet-call-embedded` aus der Gitea-npm-Registry auf rohana, +aber **im Repo steht nirgends, dass der Scope `@sorb` dorthin zeigt**. Es gibt weder eine +`.npmrc` im Wurzelverzeichnis noch in `apps/web`, und die CI setzt auch keine. + +Dass es trotzdem funktioniert, liegt allein am Lockfile: `pnpm-lock.yaml` pinnt die vollständige +Tarball-URL + +``` +tarball: https://rohana.axion1337.de/api/packages/sorb/npm/%40sorb%2F…tgz +``` + +und die CI installiert mit `--frozen-lockfile`. Solange niemand die Version anhebt, wird der +Scope nie aufgelöst — und der fehlende Eintrag fällt nicht auf. + +Aufgefallen beim Anheben auf `0.19.2-threadnet.8` (#0054): `pnpm install` griff nach +`registry.npmjs.org` und brach ab. + +``` +ERR_PNPM_FETCH_404 GET https://registry.npmjs.org/@sorb%2Fthreadnet-call-embedded: Not Found +``` + +Die Anhebung ging nur durch, weil der Scope für diesen einen Aufruf von Hand gesetzt wurde: + +```sh +env 'npm_config_@sorb:registry=https://rohana.axion1337.de/api/packages/sorb/npm/' pnpm install +``` + +Das steht in keiner Doku. Der nächste, der die Abhängigkeit anhebt, läuft in dieselbe Wand. + +## Warum das mehr ist als eine Unbequemlichkeit + +Der heutige Fehlschlag ist **laut** — 404, Abbruch, niemand baut versehentlich etwas Falsches. +Laut ist gut. Der Punkt ist, dass die Lautstärke von einer Bedingung abhängt, die uns nicht +gehört: `@sorb/threadnet-call-embedded` existiert auf `registry.npmjs.org` **derzeit nicht**. + +Registriert dort jemand diesen Namen, löst genau derselbe Befehl nicht mehr mit 404 auf, sondern +**erfolgreich — gegen ein fremdes Paket**. Das ist das Muster, das als *dependency confusion* +bekannt ist, und die Bedingung dafür ist nicht „ein Angriff auf uns", sondern „jemand legt einen +Scope-Namen an". Der Schutz besteht heute ausschließlich darin, dass ein Name auf einer fremden +Registry noch frei ist. + +Verschärfend: Der Fehler träfe genau den Moment, in dem jemand eine Version anhebt — also den +Moment, in dem eine neue Abhängigkeit ohnehin erwartet wird und ein Download nicht auffällt. + +Das ist dieselbe Klasse wie die Befunde aus #0054 und der Backup-Reihe: **die Absicherung besteht +nicht, sie ergibt sich nur zufällig aus dem aktuellen Zustand.** Sie „meldet" auch nichts — sie +funktioniert stillschweigend, bis sie es nicht mehr tut. + +## Acceptance + +- Eine **eingecheckte** `.npmrc` in `ThreadNet-Web` bindet den Scope fest: + `@sorb:registry=https://rohana.axion1337.de/api/packages/sorb/npm/` +- Ein Anheben der Version funktioniert im **frischen Klon ohne Zusatzschritte** — das ist der + eigentliche Nachweis, nicht das Vorhandensein der Datei. +- Gegenprobe: Ein Lauf mit absichtlich unerreichbarer rohana **scheitert**, statt auf + `registry.npmjs.org` auszuweichen. +- Die anderen Repos der Gruppe sind auf denselben Befund geprüft: Wer sonst noch `@sorb`-Pakete + zieht, hat dieselbe Lücke (`threadnet-call` selbst publisht nur, konsumiert aber ggf. auch). +- Der Auslieferungsweg in `ThreadNet-Web:docs/axion1337-fork.md` nennt den Befehl zum Anheben. + +## Notes + +**Kein Token nötig.** Der Lesezugriff auf die Registry ist anonym möglich (nachgeprüft: der +Paket-Index antwortet ohne Authentifizierung). Die `.npmrc` enthält damit **nur eine URL und kein +Geheimnis** und kann bedenkenlos eingecheckt werden — das ist der Grund, warum hier kein +Secrets-Handling dranhängt. + +**Warum nicht einfach dokumentieren:** Ein Satz in der Fork-Doku würde den 404 erklären, aber die +`registry.npmjs.org`-Auflösung nicht verhindern. Nach der Lehre aus #0053 und dem Bindmount-Fall +ist Aufschreiben hier ausdrücklich **nicht** die Maßnahme: die Regel war beide Male vorhanden und +hat den Fehler nicht verhindert. Wirksam ist die eingecheckte Datei, weil sie den falschen Weg +gar nicht erst offen lässt. + +**Verwandt, aber getrennt:** Bei der Gelegenheit ist aufgefallen, dass der Job `publish_npm` in +`threadnet-call` `allow_failure: true` trägt — ein *scheiternder* Publish färbt die Pipeline +nicht rot. Das ist ein eigener Befund und gehört nicht in dieses Issue; hier nur notiert, damit +er nicht verloren geht.