build(quick-261009-p0m): Laufzeitabbilder ohne Entwicklungswerkzeuge

- api: eigene Stufe prod-deps (nur Betriebsabhaengigkeiten, Prisma-Client dort erzeugt), Laufzeitstufe direkt von node:24-alpine
- api und web: npm, npx, corepack und yarn des Node-Abbilds entfernt
- api-Abbild 1,59 auf 1,12 GB; Fundzahl 3 kritisch/45 hoch auf 0 kritisch/6 hoch
- Beleg: Start gegen frische Datenbank (63 Migrationen), Rauchtests am neuen Stack
- Sicherheitsprotokoll, Betriebs- und Entwicklungsanleitung, CHANGELOG

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 20:29:00 +02:00
parent 072f9551dc
commit 2a8a7d4270
6 changed files with 65 additions and 12 deletions
+2
View File
@@ -31,6 +31,7 @@ Diese Liste beschreibt in einfachen Worten, was sich von Version zu Version an T
- DKV-Rechnung: Die Modulbeschreibung im Marktplatz weist jetzt darauf hin, dass das Modul die Freigabestufe „Verwalten“ benötigt. Mit „Benutzen“ erscheint es zwar in der Seitenleiste, öffnet aber nur die Seite „Kein Zugriff“. Modulversion 1.1.0. - DKV-Rechnung: Die Modulbeschreibung im Marktplatz weist jetzt darauf hin, dass das Modul die Freigabestufe „Verwalten“ benötigt. Mit „Benutzen“ erscheint es zwar in der Seitenleiste, öffnet aber nur die Seite „Kein Zugriff“. Modulversion 1.1.0.
- Nextcloud-Status: Über der Kachelliste gibt es jetzt ein Suchfeld. Es zeigt nur die Clouds, deren Kundenname den eingegebenen Text enthält; Groß- und Kleinschreibung spielen keine Rolle, die gewählte Sortierung bleibt erhalten. Die Kacheln sind kompakter, der Kundenname und die Adresse der Cloud stehen in voller Länge da, statt abgeschnitten zu werden. Die Knöpfe Benachrichtigen, Prüfen und Bearbeiten sitzen jetzt unten rechts neben „Zuletzt geprüft“. - Nextcloud-Status: Über der Kachelliste gibt es jetzt ein Suchfeld. Es zeigt nur die Clouds, deren Kundenname den eingegebenen Text enthält; Groß- und Kleinschreibung spielen keine Rolle, die gewählte Sortierung bleibt erhalten. Die Kacheln sind kompakter, der Kundenname und die Adresse der Cloud stehen in voller Länge da, statt abgeschnitten zu werden. Die Knöpfe Benachrichtigen, Prüfen und Bearbeiten sitzen jetzt unten rechts neben „Zuletzt geprüft“.
- Nextcloud-Status: Als Logo können Sie jetzt auch eine Bildadresse eingeben, die mit http:// beginnt. Tessera holt das Bild beim Speichern einmalig ab und behält es wie ein hochgeladenes Bild (höchstens 1 MB; PNG, JPEG, GIF oder WebP). Adressen, die nur intern erreichbar sind, holt Tessera nicht ab – solche Bilder laden Sie über „Bild hochladen“ hoch. Adressen mit https:// lädt weiterhin direkt Ihr Browser. Das Feld heißt jetzt „Bildadresse“. - Nextcloud-Status: Als Logo können Sie jetzt auch eine Bildadresse eingeben, die mit http:// beginnt. Tessera holt das Bild beim Speichern einmalig ab und behält es wie ein hochgeladenes Bild (höchstens 1 MB; PNG, JPEG, GIF oder WebP). Adressen, die nur intern erreichbar sind, holt Tessera nicht ab – solche Bilder laden Sie über „Bild hochladen“ hoch. Adressen mit https:// lädt weiterhin direkt Ihr Browser. Das Feld heißt jetzt „Bildadresse“.
- Sicherheit: Die ausgelieferten Server-Abbilder sind kleiner und enthalten keine Entwicklungswerkzeuge und keine Paketverwaltung mehr (das Server-Abbild fiel von 1,59 auf 1,12 GB, die Zahl bekannter Schwachstellen darin deutlich). Für Sie ändert sich im Alltag nichts; wer Befehle direkt im Container ausführt, nutzt dafür `node` statt `pnpm` oder `npm`.
### Behoben ### Behoben
@@ -40,6 +41,7 @@ Diese Liste beschreibt in einfachen Worten, was sich von Version zu Version an T
- Zertifikatsmanager: Beim Zusammenführen ersetzte eine zweite Datei die erste; jetzt bleiben alle Dateien in der Liste. Zertifikate und Schlüssel mit elliptischen Kurven (EC) wurden bisher nicht erkannt; jetzt funktionieren sie in allen Reitern. - Zertifikatsmanager: Beim Zusammenführen ersetzte eine zweite Datei die erste; jetzt bleiben alle Dateien in der Liste. Zertifikate und Schlüssel mit elliptischen Kurven (EC) wurden bisher nicht erkannt; jetzt funktionieren sie in allen Reitern.
- Desktop-App: Dateien lassen sich jetzt auch in der Desktop-App per Ziehen und Ablegen hochladen, zum Beispiel im Modul Dateien oder im Zertifikatsmanager. Bisher übernahm die App das Ablegen selbst, und auf der Seite kam nichts an (Linux und Windows). Dafür ist die neue Version der Desktop-App nötig. - Desktop-App: Dateien lassen sich jetzt auch in der Desktop-App per Ziehen und Ablegen hochladen, zum Beispiel im Modul Dateien oder im Zertifikatsmanager. Bisher übernahm die App das Ablegen selbst, und auf der Seite kam nichts an (Linux und Windows). Dafür ist die neue Version der Desktop-App nötig.
- Nextcloud-Status: Das Formular zum Hinzufügen und Bearbeiten einer Cloud zeigte bei manchen Eingaben englische Meldungen (zum Beispiel bei einer Bildadresse mit http://). Alle Hinweise in diesem Formular erscheinen jetzt auf Deutsch (bei englischer Spracheinstellung auf Englisch). - Nextcloud-Status: Das Formular zum Hinzufügen und Bearbeiten einer Cloud zeigte bei manchen Eingaben englische Meldungen (zum Beispiel bei einer Bildadresse mit http://). Alle Hinweise in diesem Formular erscheinen jetzt auf Deutsch (bei englischer Spracheinstellung auf Englisch).
- Sicherheit: Gespeicherte Zugangsdaten (Passwörter für Postfächer, Kalender und das Verzeichnis) werden beim Entschlüsseln jetzt strenger geprüft: Ein Datensatz, dessen Echtheits-Code gekürzt oder verändert wurde, wird abgewiesen. Alle bisher gespeicherten Zugangsdaten bleiben unverändert lesbar.
## 1.10.1 – 2026-10-06 ## 1.10.1 – 2026-10-06
+24 -7
View File
@@ -25,7 +25,23 @@ COPY tsconfig.base.json ./
RUN pnpm --filter=@tessera/api exec prisma generate RUN pnpm --filter=@tessera/api exec prisma generate
RUN pnpm --filter=@tessera/api build RUN pnpm --filter=@tessera/api build
FROM base AS runner # quick-261009-p0m: Laufzeit-Abhaengigkeiten ohne Entwicklungswerkzeuge. Eigene Stufe,
# weil der Ordnername von @prisma/client im pnpm-Speicher von den aufgeloesten
# Peer-Paketen abhaengt: der Prisma-Client wird deshalb HIER erzeugt (postinstall von
# apps/api, braucht das Schema vor der Installation) und samt Ordner uebernommen,
# statt einen Pfad aus der Builder-Stufe fest einzutragen.
FROM base AS prod-deps
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/api/package.json ./apps/api/
COPY packages/shared/package.json ./packages/shared/
COPY apps/api/prisma ./apps/api/prisma/
RUN pnpm install --frozen-lockfile --prod --filter=@tessera/api...
# quick-261009-p0m: Laufzeitstufe direkt vom Node-Abbild (ohne das vorbereitete pnpm
# der Stufe base). Die Paketverwaltungen des Node-Abbilds (npm, npx, corepack, yarn)
# werden gleich als Erstes entfernt -- im Betrieb installiert nichts nach.
FROM node:24-alpine AS runner
WORKDIR /app WORKDIR /app
ENV NODE_ENV=production ENV NODE_ENV=production
ARG APP_VERSION ARG APP_VERSION
@@ -33,17 +49,18 @@ ARG APP_CHANNEL
ARG APP_COMMIT ARG APP_COMMIT
ARG APP_BUILD_TIME ARG APP_BUILD_TIME
ENV APP_VERSION=$APP_VERSION APP_CHANNEL=$APP_CHANNEL APP_COMMIT=$APP_COMMIT APP_BUILD_TIME=$APP_BUILD_TIME ENV APP_VERSION=$APP_VERSION APP_CHANNEL=$APP_CHANNEL APP_COMMIT=$APP_COMMIT APP_BUILD_TIME=$APP_BUILD_TIME
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/corepack /opt/yarn-v1.22.22 \
/usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack /usr/local/bin/yarn /usr/local/bin/yarnpkg
RUN addgroup --system --gid 1001 nestjs && \ RUN addgroup --system --gid 1001 nestjs && \
adduser --system --uid 1001 nestjs && \ adduser --system --uid 1001 nestjs && \
mkdir -p /app/user-files && \ mkdir -p /app/user-files && \
chown nestjs:nestjs /app/user-files chown nestjs:nestjs /app/user-files
COPY --from=deps /app/package.json /app/pnpm-workspace.yaml /app/pnpm-lock.yaml ./ COPY --from=prod-deps /app/package.json /app/pnpm-workspace.yaml /app/pnpm-lock.yaml ./
COPY --from=deps /app/node_modules ./node_modules COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=deps /app/apps/api/node_modules ./apps/api/node_modules COPY --from=prod-deps /app/apps/api/node_modules ./apps/api/node_modules
COPY --from=deps /app/apps/api/package.json ./apps/api/ COPY --from=prod-deps /app/apps/api/package.json ./apps/api/
COPY --from=deps /app/packages/shared/package.json ./packages/shared/ COPY --from=prod-deps /app/packages/shared/package.json ./packages/shared/
COPY --from=builder /app/apps/api/dist ./apps/api/dist COPY --from=builder /app/apps/api/dist ./apps/api/dist
COPY --from=builder /app/node_modules/.pnpm/@prisma+client@6.19.3_prisma@6.19.3_typescript@5.9.3__typescript@5.9.3/node_modules/.prisma ./node_modules/.pnpm/@prisma+client@6.19.3_prisma@6.19.3_typescript@5.9.3__typescript@5.9.3/node_modules/.prisma
COPY --from=builder /app/apps/api/prisma ./apps/api/prisma COPY --from=builder /app/apps/api/prisma ./apps/api/prisma
COPY --from=builder /app/packages/shared/src ./packages/shared/src COPY --from=builder /app/packages/shared/src ./packages/shared/src
COPY apps/api/scripts ./apps/api/scripts COPY apps/api/scripts ./apps/api/scripts
+4
View File
@@ -42,6 +42,10 @@ ARG APP_CHANNEL
ARG APP_COMMIT ARG APP_COMMIT
ARG APP_BUILD_TIME ARG APP_BUILD_TIME
ENV APP_VERSION=$APP_VERSION APP_CHANNEL=$APP_CHANNEL APP_COMMIT=$APP_COMMIT APP_BUILD_TIME=$APP_BUILD_TIME ENV APP_VERSION=$APP_VERSION APP_CHANNEL=$APP_CHANNEL APP_COMMIT=$APP_COMMIT APP_BUILD_TIME=$APP_BUILD_TIME
# quick-261009-p0m: Paketverwaltungen des Node-Abbilds (npm, npx, corepack, yarn) entfernen;
# der Web-Server braucht nur `node`.
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/corepack /opt/yarn-v1.22.22 \
/usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack /usr/local/bin/yarn /usr/local/bin/yarnpkg
RUN addgroup --system --gid 1001 nodejs && \ RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs adduser --system --uid 1001 nextjs
COPY --from=builder /app/apps/web/public ./apps/web/public COPY --from=builder /app/apps/web/public ./apps/web/public
+8
View File
@@ -410,6 +410,14 @@ protokolliert die durchgelaufenen Prisma-Migrationen sowie zuletzt
Kanal und Kurzkennung des Standes, der gerade läuft (siehe Kapitel 9). Erst danach Kanal und Kurzkennung des Standes, der gerade läuft (siehe Kapitel 9). Erst danach
startet `web`, weil `depends_on: api: condition: service_healthy` das erzwingt. startet `web`, weil `depends_on: api: condition: service_healthy` das erzwingt.
**Befehle im Container:** Die Container von `api` und `web` enthalten keine Paketverwaltung
(kein npm, pnpm, npx oder yarn) und keine Entwicklungswerkzeuge – das Abbild trägt nur, was zum
Laufen nötig ist (und ist dadurch beim Server-Abbild deutlich kleiner; Näheres im
[Sicherheitsprotokoll](sicherheitsprotokoll.md)). Befehle im Container laufen deshalb direkt mit
`node`, zum Beispiel `docker compose exec api node -e "console.log('ok')"`. Ein Befehl wie
`docker compose exec api pnpm …` oder `… npm …` funktioniert nicht mehr. Die Migrationen führt
weiterhin das Startskript aus (Kapitel 5), dafür müssen Sie nichts von Hand tun.
| Symptom | Wahrscheinliche Ursache | Prüfen / Beheben | | Symptom | Wahrscheinliche Ursache | Prüfen / Beheben |
|---|---|---| |---|---|---|
| `docker compose up` bricht sofort ab, ohne dass ein Container startet, mit einer Meldung zu `TESSERA_ENCRYPTION_KEY` | Variable fehlt in `.env` – Compose selbst verweigert die Variablen-Interpolation (`${TESSERA_ENCRYPTION_KEY:?...}`) | `TESSERA_ENCRYPTION_KEY` setzen (siehe Kapitel 2), danach erneut starten. | | `docker compose up` bricht sofort ab, ohne dass ein Container startet, mit einer Meldung zu `TESSERA_ENCRYPTION_KEY` | Variable fehlt in `.env` – Compose selbst verweigert die Variablen-Interpolation (`${TESSERA_ENCRYPTION_KEY:?...}`) | `TESSERA_ENCRYPTION_KEY` setzen (siehe Kapitel 2), danach erneut starten. |
+16
View File
@@ -970,6 +970,22 @@ nicht weiter. Der Ordner `security-reports/` ist von Git ausgeschlossen.
## Konventionen und Fallstricke ## Konventionen und Fallstricke
**Laufzeitabbilder ohne Entwicklungswerkzeuge (quick-261009-p0m):** Das Server-Abbild
(`apps/api/Dockerfile`) hat eine eigene Stufe `prod-deps`: dort läuft
`pnpm install --frozen-lockfile --prod --filter=@tessera/api...`, und der Prisma-Client wird in
genau dieser Stufe erzeugt (der `postinstall` von `apps/api` braucht das Schema vor der
Installation, deshalb wird `apps/api/prisma` vorher kopiert). Ein fester Pfad aus der
Builder-Stufe wäre fehleranfällig, weil der Ordnername von `@prisma/client` im pnpm-Speicher von
den aufgelösten Peer-Paketen abhängt. Die Laufzeitstufe beider Abbilder (`api` und `web`) kommt
direkt aus `node:24-alpine` und entfernt als Erstes npm, npx, corepack und yarn. Im Container gibt
es dadurch kein `pnpm` und kein `npm` mehr; Befehle laufen mit `node` (der Prisma-Aufruf des
Startskripts liegt unter `apps/api/node_modules/.bin/prisma`). **Falle:** Importiert Laufzeit-Code
ein Paket, das nur unter `devDependencies` steht, scheitert das erst im Container – die Unit-Tests
laufen mit allen Abhängigkeiten und fangen es nicht. Dann gehört das Paket in `dependencies`.
**Beweis nach jeder Änderung an den Abbildern:** ein Start gegen eine frische, leere Datenbank (alle
Migrationen laufen, die Zeile „Tessera API running“ erscheint) plus die Rauchtests am neu gebauten
Stack – so wie es `checks/fresh-db-start.sh` im Auftrag quick-261009-p0m vormacht.
**NestJS-Routenreihenfolge:** NestJS matcht Routen in Deklarationsreihenfolge. Eine statische Route **NestJS-Routenreihenfolge:** NestJS matcht Routen in Deklarationsreihenfolge. Eine statische Route
wie `@Get('source-config')` **muss vor** einem `@Get(':id')`-Platzhalter derselben Klasse stehen — wie `@Get('source-config')` **muss vor** einem `@Get(':id')`-Platzhalter derselben Klasse stehen —
sonst interpretiert der Platzhalter den literalen Pfadteil als `id` und "beschattet" die statische sonst interpretiert der Platzhalter den literalen Pfadteil als `id` und "beschattet" die statische
+11 -5
View File
@@ -12,11 +12,11 @@ Das Protokoll enthält bewusst keine Passwörter, keine Zugangsdaten und keine A
- **Zugangsdaten im Quelltext:** Es wurden keine echten Passwörter oder Schlüssel gefunden. Die gesamte Änderungsgeschichte des Projekts wurde durchsucht; alle 20 Treffer waren Fehlalarme, nämlich Testschlüssel, Beschriftungen und Beispiele in Notizen. - **Zugangsdaten im Quelltext:** Es wurden keine echten Passwörter oder Schlüssel gefunden. Die gesamte Änderungsgeschichte des Projekts wurde durchsucht; alle 20 Treffer waren Fehlalarme, nämlich Testschlüssel, Beschriftungen und Beispiele in Notizen.
- **Fremde Bausteine:** Die erste Prüfung verzeichnete 151 bekannte Schwachstellen in den Bausteinen anderer Hersteller, die Tessera im Betrieb verwendet, davon 5 kritische und 73 hohe. Am 9. Oktober 2026 wurden die Bausteine innerhalb ihrer bisherigen Versionslinien aktualisiert und zwei ungenutzte Bausteine entfernt; danach sind es 12 (0 kritische, 9 hohe, 3 mittlere). Die übrigen 12 haben keine bereinigte Fassung in der verwendeten Versionslinie (xlsx, node-forge) oder werden erst in einer neuen Hauptversion behoben (nodemailer, sharp, deepmerge-ts); sie sind unter „Einordnung der Befunde“ mit Grund eingeordnet. - **Fremde Bausteine:** Die erste Prüfung verzeichnete 151 bekannte Schwachstellen in den Bausteinen anderer Hersteller, die Tessera im Betrieb verwendet, davon 5 kritische und 73 hohe. Am 9. Oktober 2026 wurden die Bausteine innerhalb ihrer bisherigen Versionslinien aktualisiert und zwei ungenutzte Bausteine entfernt; danach sind es 12 (0 kritische, 9 hohe, 3 mittlere). Die übrigen 12 haben keine bereinigte Fassung in der verwendeten Versionslinie (xlsx, node-forge) oder werden erst in einer neuen Hauptversion behoben (nodemailer, sharp, deepmerge-ts); sie sind unter „Einordnung der Befunde“ mit Grund eingeordnet.
- **Eigener Quelltext:** Ein einziger echter Härtungspunkt wurde gefunden (die Längenprüfung bei der Entschlüsselung gespeicherter Geheimnisse, Schweregrad niedrig). Alles andere sind Fehlalarme oder bewusste, dokumentierte Entscheidungen. - **Eigener Quelltext:** Ein einziger echter Härtungspunkt wurde gefunden (die Längenprüfung bei der Entschlüsselung gespeicherter Geheimnisse, Schweregrad niedrig); er ist am 9. Oktober 2026 behoben und durch Tests abgesichert. Alles andere sind Fehlalarme oder bewusste, dokumentierte Entscheidungen.
- **Automatische Prüfung:** Seit dem 9. Oktober 2026 läuft nach jedem Bau der Plattform automatisch eine Sicherheitsprüfung. Sie meldet nur und hält den Bau nie an. - **Automatische Prüfung:** Seit dem 9. Oktober 2026 läuft nach jedem Bau der Plattform automatisch eine Sicherheitsprüfung. Sie meldet nur und hält den Bau nie an.
- **Prüfung von außen:** Vor jeder Freigabe wird der Testserver alpha wie ein Besucher ohne Konto angesehen, rein passiv und ohne Angriffe. Der erste Lauf am 9. Oktober 2026 (direkt gegen die Anwendung, ohne den vorgeschalteten Proxy) fand nichts Hohes, 2 mittlere und 6 niedrige Hinweise sowie 3 reine Informationen; alle betreffen fehlende Schutz-Kopfzeilen der Weboberfläche. Der Lauf über die öffentliche Adresse steht noch aus. - **Prüfung von außen:** Vor jeder Freigabe wird der Testserver alpha wie ein Besucher ohne Konto angesehen, rein passiv und ohne Angriffe. Der erste Lauf am 9. Oktober 2026 (direkt gegen die Anwendung, ohne den vorgeschalteten Proxy) fand nichts Hohes, 2 mittlere und 6 niedrige Hinweise sowie 3 reine Informationen; alle betreffen fehlende Schutz-Kopfzeilen der Weboberfläche. Der Lauf über die öffentliche Adresse steht noch aus.
- **Bisherige Prüfungen:** Acht Code-Prüfungen größerer Änderungen mit zusammen 89 Befunden; 76 davon sind behoben, die übrigen 13 sind Hinweise der niedrigsten Stufe. Alle kritischen Befunde und alle Warnungen sind behoben. - **Bisherige Prüfungen:** Acht Code-Prüfungen größerer Änderungen mit zusammen 89 Befunden; 76 davon sind behoben, die übrigen 13 sind Hinweise der niedrigsten Stufe. Alle kritischen Befunde und alle Warnungen sind behoben.
- **Was noch zu tun ist:** Die fertigen Abbilder sollen keine Entwicklungswerkzeuge mehr enthalten, die Härtung der Längenprüfung bei der Entschlüsselung steht aus, und die offenen Bausteine werden bei neuen Fassungen der Hersteller erneut angesehen. Der Stand jedes einzelnen Punkts steht in der Tabelle „Einordnung der Befunde“. - **Was noch zu tun ist:** Die Abbilder enthalten seit dem 9. Oktober 2026 keine Entwicklungswerkzeuge und keine Paketverwaltung mehr (das Server-Abbild ist von 1,59 auf 1,12 GB geschrumpft, seine Fundzahl von 3 kritischen und 45 hohen auf 0 kritische und 6 hohe gefallen). Offen bleiben einzelne Bausteine ohne bereinigte Fassung und die Bausteine, die erst mit einer neuen Hauptversion zu beheben sind; sie werden bei neuen Fassungen der Hersteller erneut angesehen. Der Stand jedes einzelnen Punkts steht in der Tabelle „Einordnung der Befunde“.
## So lesen Sie dieses Protokoll ## So lesen Sie dieses Protokoll
@@ -195,11 +195,11 @@ Die Tabelle beurteilt jeden Befund der ersten vollständigen Prüfung. Sie wird
| Zwei mittelbare Bausteine ohne bereinigte Fassung in der Versionslinie: Bildbaustein sharp 0.34.5 (im Webframework) und deepmerge-ts 7.1.5 (in der Datenbank-Werkzeugkette) | Weboberfläche, Server | Hoch (3 und 1) | offen | Die Korrektur liegt bei sharp erst in 0.35 (eine neue Nebenversion der Null-Linie, die wie eine Hauptversion behandelt wird), bei deepmerge-ts in Version 8. Die Meldungen zu sharp betreffen das Dekodieren präparierter Bilddateien (libvips, libheif, librsvg); sharp gehört zur Bild-Optimierung des Webframeworks, und in der Konfiguration sind keine fremden Bildquellen freigegeben, sodass nur eigene Dateien verarbeitet werden. deepmerge-ts steckt im Werkzeug der Datenbank-Anbindung, das mit der Datenbank-Hauptversion (Prisma 6.19.3 bleibt exakt festgelegt) mitgeführt wird. Beide werden mit der jeweils nächsten Hauptversion ihres Elternpakets behoben | | Zwei mittelbare Bausteine ohne bereinigte Fassung in der Versionslinie: Bildbaustein sharp 0.34.5 (im Webframework) und deepmerge-ts 7.1.5 (in der Datenbank-Werkzeugkette) | Weboberfläche, Server | Hoch (3 und 1) | offen | Die Korrektur liegt bei sharp erst in 0.35 (eine neue Nebenversion der Null-Linie, die wie eine Hauptversion behandelt wird), bei deepmerge-ts in Version 8. Die Meldungen zu sharp betreffen das Dekodieren präparierter Bilddateien (libvips, libheif, librsvg); sharp gehört zur Bild-Optimierung des Webframeworks, und in der Konfiguration sind keine fremden Bildquellen freigegeben, sodass nur eigene Dateien verarbeitet werden. deepmerge-ts steckt im Werkzeug der Datenbank-Anbindung, das mit der Datenbank-Hauptversion (Prisma 6.19.3 bleibt exakt festgelegt) mitgeführt wird. Beide werden mit der jeweils nächsten Hauptversion ihres Elternpakets behoben |
| Tabellenbaustein xlsx 0.18.5 | Server (Import Handelsware, Export DKV) | Hoch (2 hoch) | offen | Die beiden Meldungen betreffen das Verändern von Objekteigenschaften und die Überlastung durch präparierte Dateien. Auf dem öffentlichen Paketverzeichnis gibt es keine bereinigte Fassung. Der Baustein liest hochgeladene Tabellen angemeldeter Benutzer mit Modulfreigabe und schreibt DKV-Exporte. Er muss durch einen anderen Baustein ersetzt werden; bis dahin begrenzt die Modulfreigabe den Kreis möglicher Angreifer | | Tabellenbaustein xlsx 0.18.5 | Server (Import Handelsware, Export DKV) | Hoch (2 hoch) | offen | Die beiden Meldungen betreffen das Verändern von Objekteigenschaften und die Überlastung durch präparierte Dateien. Auf dem öffentlichen Paketverzeichnis gibt es keine bereinigte Fassung. Der Baustein liest hochgeladene Tabellen angemeldeter Benutzer mit Modulfreigabe und schreibt DKV-Exporte. Er muss durch einen anderen Baustein ersetzt werden; bis dahin begrenzt die Modulfreigabe den Kreis möglicher Angreifer |
| Zertifikatsbaustein node-forge 1.4.0 | Server (Zertifikatsmanager) | Hoch (1 hoch) | offen | Es ist keine bereinigte Fassung verzeichnet. Der Fehler betrifft das Prüfen von Unterschriften; im Zertifikatsmanager dient diese Prüfung dem Ordnen und Anzeigen der Kette, eine Zugriffsentscheidung hängt nicht daran. Der Baustein liest nur Dateien, die angemeldete Benutzer mit Modulfreigabe selbst hochladen; Größe, Anzahl und Rechenaufwand sind begrenzt. Er wird beobachtet und bei Erscheinen einer Korrektur aktualisiert | | Zertifikatsbaustein node-forge 1.4.0 | Server (Zertifikatsmanager) | Hoch (1 hoch) | offen | Es ist keine bereinigte Fassung verzeichnet. Der Fehler betrifft das Prüfen von Unterschriften; im Zertifikatsmanager dient diese Prüfung dem Ordnen und Anzeigen der Kette, eine Zugriffsentscheidung hängt nicht daran. Der Baustein liest nur Dateien, die angemeldete Benutzer mit Modulfreigabe selbst hochladen; Größe, Anzahl und Rechenaufwand sind begrenzt. Er wird beobachtet und bei Erscheinen einer Korrektur aktualisiert |
| Entwicklungswerkzeuge im Server-Abbild (tinypool, tar, pnpm) | Abbild `api` | Hoch (6 kritisch, 116 hoch im Abbild insgesamt) | offen | Das Abbild enthält Werkzeuge zum Testen und Bauen, die im Betrieb nichts tun, aber Schwachstellen mitbringen. Das fertige Abbild soll nur noch enthalten, was zum Laufen nötig ist | | Entwicklungswerkzeuge im Server-Abbild (tinypool, tar, pnpm) | Abbild `api` | Hoch (damals 6 kritisch, 116 hoch im Abbild insgesamt) | behoben (9. Oktober 2026) | Das Abbild bringt jetzt nur noch mit, was zum Laufen nötig ist: Es gibt eine eigene Bauphase, die ausschließlich die Bausteine für den Betrieb installiert (samt dem fertig erzeugten Datenbank-Baustein), die Laufzeit-Stufe stammt direkt aus dem Node-Abbild und enthält keine Test- und Bauwerkzeuge mehr. Bewiesen durch einen Start gegen eine frische Datenbank (alle 63 Migrationen laufen durch, die API meldet sich) und durch die Rauchtests am neu gebauten Stack. Größe 1,59 auf 1,12 GB; Fundzahl des Abbilds von 3 kritisch / 45 hoch auf 0 kritisch / 6 hoch (Messung mit Trivy, Betriebssystem und Bausteine zusammen, nach den Aktualisierungen vom selben Tag) |
| Paketverwalter npm im Node-Grundabbild | Abbild `web` | Hoch (Teil von 2 kritisch, 19 hoch) | offen | Das Grundabbild bringt einen Paketverwalter mit eigenen Bausteinen mit, der im Betrieb nicht gebraucht wird. Er soll aus dem fertigen Abbild entfernt werden | | Paketverwalter npm im Node-Grundabbild | Abbilder `web` und `api` | Hoch (damals Teil von 2 kritisch, 19 hoch) | behoben (9. Oktober 2026) | Die Paketverwaltungen des Node-Grundabbilds (npm, npx, corepack, yarn) werden in beiden Laufzeit-Stufen als Erstes entfernt, im Betrieb installiert nichts nach. Das Abbild `web` fiel von 11 hohen auf 3 hohe Funde (0 kritisch). Die Größe des Web-Abbilds bleibt bei 359 MB, weil Docker gelöschte Dateien aus einer früheren Schicht nicht herausrechnet; die Funde zählen trotzdem weniger, weil Trivy nur die sichtbaren Dateien betrachtet. Die Paketverwaltung des Betriebssystems (apk) bleibt bestehen |
| Desktop-App: Baustein rustls 0.23.41 (Verschlüsselung der Verbindung) | Desktop-App | Mittel | behoben (9. Oktober 2026) | Auf 0.23.45 derselben Versionslinie angehoben (dabei zog der Paketverwalter den Begleitbaustein rustls-webpki von 0.103.13 auf 0.103.15 mit). Übersetzen und Codeprüfung der Desktop-App laufen fehlerfrei. Die nächste Fassung der Desktop-App muss neu gebaut werden, damit die Korrektur ausgeliefert wird | | Desktop-App: Baustein rustls 0.23.41 (Verschlüsselung der Verbindung) | Desktop-App | Mittel | behoben (9. Oktober 2026) | Auf 0.23.45 derselben Versionslinie angehoben (dabei zog der Paketverwalter den Begleitbaustein rustls-webpki von 0.103.13 auf 0.103.15 mit). Übersetzen und Codeprüfung der Desktop-App laufen fehlerfrei. Die nächste Fassung der Desktop-App muss neu gebaut werden, damit die Korrektur ausgeliefert wird |
| Desktop-App: Baustein glib 0.18.5 | Desktop-App (Linux-Oberfläche) | Mittel | offen | Die Korrektur liegt erst in Version 0.20, die zur Oberflächen-Bibliothek des Desktop-Frameworks gehört. Ein Wechsel ist nur mit deren Aktualisierung möglich | | Desktop-App: Baustein glib 0.18.5 | Desktop-App (Linux-Oberfläche) | Mittel | offen | Die Korrektur liegt erst in Version 0.20, die zur Oberflächen-Bibliothek des Desktop-Frameworks gehört. Ein Wechsel ist nur mit deren Aktualisierung möglich |
| Länge der Echtheitsprüfung bei AES-GCM (Entschlüsselung gespeicherter Geheimnisse) | Server, `crypto.service.ts` | Niedrig | offen | Beim Entschlüsseln wird die Länge des Echtheits-Codes nicht erzwungen. Ein Angreifer bräuchte dafür schreibenden Zugriff auf die Datenbank. Alle bisher gespeicherten Werte nutzen die volle Länge, die Härtung ist ohne Datenverlust möglich | | Länge der Echtheitsprüfung bei AES-GCM (Entschlüsselung gespeicherter Geheimnisse) | Server, `crypto.service.ts` | Niedrig | behoben (9. Oktober 2026) | Die Entschlüsselung verlangt jetzt genau die volle Länge des Echtheits-Codes (16 Byte) und weist alles andere ab; die Länge wird zusätzlich an die Verschlüsselungsfunktion übergeben. Alle bisher gespeicherten Werte nutzen die volle Länge und bleiben lesbar. Tests: ein auf 4 Byte gekürzter Code, ein zu langer und ein leerer Code sowie ein Code mit einem veränderten Bit werden abgewiesen (vor der Änderung wurde der gekürzte Code noch akzeptiert), der normale Hin- und Rückweg inklusive leerem Text und Umlauten funktioniert weiter |
| Vier abschaltbare Zertifikatsprüfungen (Verzeichnisdienst, Proxmox-Anmeldung, Proxmox-Abfragen, Symbolsuche) | Server | Mittel laut Werkzeug | bewusst akzeptiert | Die Prüfung entfällt nur, wenn ein Administrator das für genau eine Verbindung ausdrücklich erlaubt, etwa bei internen Servern mit selbst ausgestellten Zertifikaten. Standard ist die volle Prüfung. Die Entscheidung ist in Kommentaren des Quelltexts mit Verweis auf den Beschluss festgehalten | | Vier abschaltbare Zertifikatsprüfungen (Verzeichnisdienst, Proxmox-Anmeldung, Proxmox-Abfragen, Symbolsuche) | Server | Mittel laut Werkzeug | bewusst akzeptiert | Die Prüfung entfällt nur, wenn ein Administrator das für genau eine Verbindung ausdrücklich erlaubt, etwa bei internen Servern mit selbst ausgestellten Zertifikaten. Standard ist die volle Prüfung. Die Entscheidung ist in Kommentaren des Quelltexts mit Verweis auf den Beschluss festgehalten |
| Testschlüssel und Testwerte in Testdaten, Testdateien und Planungsnotizen | Zertifikatsmanager (Testdaten), drei Testdateien, eine Planungsnotiz, eine Testkomponente | Fehlalarm | bewusst akzeptiert | Die Schlüssel sind eigens zum Prüfen der Software erzeugt und schützen nichts. Der Ordner mit den Testdaten und die einzelnen Dateien stehen in den Ausnahmelisten (gitleaks, Trivy, Semgrep) | | Testschlüssel und Testwerte in Testdaten, Testdateien und Planungsnotizen | Zertifikatsmanager (Testdaten), drei Testdateien, eine Planungsnotiz, eine Testkomponente | Fehlalarm | bewusst akzeptiert | Die Schlüssel sind eigens zum Prüfen der Software erzeugt und schützen nichts. Der Ordner mit den Testdaten und die einzelnen Dateien stehen in den Ausnahmelisten (gitleaks, Trivy, Semgrep) |
| Beschriftung „Benutzer/Passwort“, Tabellenzeile einer Prüfliste und Beispielaufruf an einen lokalen Wegwerf-Testserver | Sprachdatei, Planungsnotizen | Fehlalarm | bewusst akzeptiert | Keines der drei enthält ein echtes Geheimnis: ein Beschriftungstext, eine Beispielzeile und der Testzugang eines wegwerfbaren lokalen Testservers. Alle drei sind einzeln in den Ausnahmelisten eingetragen | | Beschriftung „Benutzer/Passwort“, Tabellenzeile einer Prüfliste und Beispielaufruf an einen lokalen Wegwerf-Testserver | Sprachdatei, Planungsnotizen | Fehlalarm | bewusst akzeptiert | Keines der drei enthält ein echtes Geheimnis: ein Beschriftungstext, eine Beispielzeile und der Testzugang eines wegwerfbaren lokalen Testservers. Alle drei sind einzeln in den Ausnahmelisten eingetragen |
@@ -240,6 +240,12 @@ Die Beurteilung jeder Meldung steht in der Tabelle „Einordnung der Befunde“.
Der neueste Eintrag steht oben. Der neueste Eintrag steht oben.
### 2026-10-09 — Eigene Härtung: Echtheits-Code und schlankere Abbilder
Zwei Maßnahmen aus der ersten Prüfung wurden umgesetzt. Erstens verlangt die Entschlüsselung gespeicherter Geheimnisse jetzt die volle Länge des Echtheits-Codes; ein gekürzter Code wird abgewiesen, vorher wurde er noch angenommen (der neue Test war vor der Änderung rot). Zweitens enthalten die fertigen Abbilder keine Entwicklungswerkzeuge und keine Paketverwaltung mehr: Das Server-Abbild wird aus einer eigenen Bauphase mit ausschließlich den Betriebsbausteinen zusammengesetzt, und beide Laufzeit-Abbilder entfernen npm, npx, corepack und yarn des Node-Grundabbilds.
**Messung (Trivy, Betriebssystem und Bausteine, nach den Aktualisierungen vom selben Tag):** Server-Abbild vorher 3 kritisch, 45 hoch, 41 mittel, 2 niedrig bei 1,59 GB, nachher 0 kritisch, 6 hoch, 4 mittel, 0 niedrig bei 1,12 GB. Web-Abbild vorher 0 kritisch, 11 hoch, 13 mittel, 1 niedrig, nachher 0 kritisch, 3 hoch, 1 mittel, 0 niedrig bei unveränderten 359 MB. **Beweis, dass nichts kaputtgegangen ist:** Ein Start des Server-Abbilds gegen eine frische, leere Datenbank wendet alle 63 Migrationen an und bringt die API zum Laufen; dazu liefen die Rauchtests am neu gebauten Stack (Zertifikatsmanager, Änderungsliste, Dateien und Übertragungen, Mailversand) fehlerfrei.
### 2026-10-09 — Bausteine von Fremdherstellern aktualisiert ### 2026-10-09 — Bausteine von Fremdherstellern aktualisiert
Alle Bausteine mit bereinigter Fassung innerhalb ihrer bisherigen Versionslinie wurden angehoben: das Webframework Next.js (15.5.19 auf 15.5.27), das Server-Framework (11.2.7, damit multer 2.4.0), der Mailversand (nodemailer 9.1.1), das Netzwerk-Paket undici (7.30.0), adm-zip (0.6.1) und csv-parse (7.0.3). Dazu kommen 15 Überschreibungen für tief eingebundene Bausteine (`pnpm.overrides`, jeweils innerhalb derselben Hauptversion) und die Entfernung der beiden ungenutzten Pakete für Mailvorlagen und die frühere Exchange-Anbindung. In der Desktop-App wurde rustls auf 0.23.45 gehoben. Prisma blieb exakt auf 6.19.3, Next.js auf der Linie 15, NestJS auf 11. Alle Bausteine mit bereinigter Fassung innerhalb ihrer bisherigen Versionslinie wurden angehoben: das Webframework Next.js (15.5.19 auf 15.5.27), das Server-Framework (11.2.7, damit multer 2.4.0), der Mailversand (nodemailer 9.1.1), das Netzwerk-Paket undici (7.30.0), adm-zip (0.6.1) und csv-parse (7.0.3). Dazu kommen 15 Überschreibungen für tief eingebundene Bausteine (`pnpm.overrides`, jeweils innerhalb derselben Hauptversion) und die Entfernung der beiden ungenutzten Pakete für Mailvorlagen und die frühere Exchange-Anbindung. In der Desktop-App wurde rustls auf 0.23.45 gehoben. Prisma blieb exakt auf 6.19.3, Next.js auf der Linie 15, NestJS auf 11.