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.