Files
nexarch/web/mail-search/app/mail/[messageId]/attachment-preview.security.test.ts
T
patrickandClaude Sonnet 5 f63fcb8a2d
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
Mail-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
UX-03: anhang-vorschau
Frontend (web/mail-search): Anhang-Vorschau fuer PDF (Canvas-Rendering
via pdfjs-dist, gleiches Muster wie DOC-05s web/pdf-viewer/PdfViewer.tsx
-- kein aequivalentes PdfCanvasPreview im Repo gefunden, daher PdfViewer
als Vorlage uebernommen statt neu erfunden) und Bilder (<img> auf einem
authentifiziert geladenen Blob). Die Vorschauart haengt ausschliesslich
vom serverseitig per Magic-Bytes bestimmten contentType ab, nie von
einem Dateinamen (den es an der Schnittstelle gar nicht gibt); nicht
unterstuetzte Typen werden nur als Hinweistext angezeigt, nie
eingebettet. Kein iframe/<object>/dangerouslySetInnerHTML -- durch
automatisierten Sicherheitsreview-Test abgesichert. Neue lib/http.ts
(authentifizierter Zugriff ueber @nexarch/shl, identisch zu
web/pdf-viewer/lib/http.ts) und lib/attachments.ts (Anhangsliste/
-inhalt der Mail-API). Pruefprotokoll in mail/docs/UX-03-PRUEFPROTOKOLL.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-16 06:51:29 +00:00

34 lines
1.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const dir = dirname(fileURLToPath(import.meta.url));
// UX-03 Pflichtprüfung 2: Sicherheitsreview bestätigt automatisiert (statt
// nur behauptet): keine iframe-Einbindung von Anhangsinhalt, kein <object>,
// kein dangerouslySetInnerHTML -- über alle an der Anhang-Vorschau
// beteiligten Dateien. archivmail hatte testweise eine iframe-PDF-Vorschau,
// als unsicher verworfen; dieser Test verhindert ein Wiederauftreten.
const previewFiles = ["PdfCanvasPreview.tsx", "ImagePreview.tsx", "AttachmentPreview.tsx", "AttachmentList.tsx"];
const forbiddenPatterns = [/<iframe/i, /<object/i, /dangerouslysetinnerhtml/i];
// Kommentare erklären absichtlich, WARUM kein iframe/object verwendet wird
// (enthalten die Begriffe also selbst als Prosa) -- der Review prüft den
// tatsächlichen Code, daher werden Kommentare vor dem Abgleich entfernt.
function stripComments(source: string): string {
return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
}
describe("Sicherheitsreview: Anhang-Vorschau rendert nie Fremdinhalt unkontrolliert", () => {
for (const file of previewFiles) {
it(`${file} enthält kein iframe/object/dangerouslySetInnerHTML im tatsächlichen Code`, () => {
const code = stripComments(readFileSync(join(dir, file), "utf-8"));
for (const pattern of forbiddenPatterns) {
expect(code).not.toMatch(pattern);
}
});
}
});