assertSafePdf: PDF-Streams vor Pattern-Scan ausblenden
Stage-Bug: User lädt zwei Handy-JPGs als PDF hoch → 415 mit "PDF enthält JavaScript-Action". Die JPEG-Bytes im jsPDF-Output enthielten zufällig die Byte-Folge "/JavaScript" → Pattern-Match auf Binär-Daten statt PDF-Struktur. Fix: stream..endstream-Blöcke vor dem Scan rauspatchen. Echte PDF-Actions stehen IMMER außerhalb von Streams (Object-Dictionaries), Binär-Streams (Bilder/Fonts/Komprimiertes) werden ignoriert. Smoke-Test: jspdf-Style-PDF mit /JavaScript-Bytes im Stream durchgewinkt, echte /OpenAction /S /JavaScript blockiert, clean PDF OK.
This commit is contained in:
@@ -276,9 +276,14 @@ export function assertSafePdf(buf: Buffer): void {
|
|||||||
if (buf.length < 5 || buf.subarray(0, 5).toString('latin1') !== '%PDF-') {
|
if (buf.length < 5 || buf.subarray(0, 5).toString('latin1') !== '%PDF-') {
|
||||||
return; // keine PDF → andere Validatoren zuständig
|
return; // keine PDF → andere Validatoren zuständig
|
||||||
}
|
}
|
||||||
const content = buf.toString('latin1');
|
// Stream-Inhalte (Bilder/Fonts/Komprimiertes) aus dem Scan rausnehmen.
|
||||||
|
// Jpeg-Bytes können zufällig "/JavaScript" enthalten → false-positive
|
||||||
|
// bei jsPDF-generierten PDFs mit eingebetteten Fotos (stage-Bug
|
||||||
|
// 2026-06-03). Echte aktive PDF-Inhalte stehen IMMER im PDF-
|
||||||
|
// Object-Stream (außerhalb von `stream..endstream`-Blöcken).
|
||||||
|
const scanTarget = buf.toString('latin1').replace(/stream\s[\s\S]*?endstream/g, '');
|
||||||
for (const { pattern, label } of PDF_DANGER_PATTERNS) {
|
for (const { pattern, label } of PDF_DANGER_PATTERNS) {
|
||||||
if (pattern.test(content)) {
|
if (pattern.test(scanTarget)) {
|
||||||
throw new ApiError(
|
throw new ApiError(
|
||||||
415,
|
415,
|
||||||
`PDF enthält nicht erlaubte aktive Inhalte (${label}). Bitte ohne JavaScript / Auto-Actions / eingebettete Dateien hochladen.`,
|
`PDF enthält nicht erlaubte aktive Inhalte (${label}). Bitte ohne JavaScript / Auto-Actions / eingebettete Dateien hochladen.`,
|
||||||
|
|||||||
@@ -97,6 +97,19 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
|||||||
|
|
||||||
## ✅ Erledigt
|
## ✅ Erledigt
|
||||||
|
|
||||||
|
- [x] **🐞 assertSafePdf: jspdf-PDFs mit JPEGs fälschlich als „JavaScript" blockiert**
|
||||||
|
- Stage-Bug: User lädt Ausweis als „JPGs → PDF" hoch → 415 mit
|
||||||
|
Meldung „PDF enthält JavaScript-Action". Backend hat den jspdf-
|
||||||
|
Output korrekt strukturell, aber die JPEG-Bytes im Image-Stream
|
||||||
|
enthielten zufällig die Byte-Folge „/JavaScript" → Pattern-Match.
|
||||||
|
- Fix: vor dem Pattern-Scan `stream..endstream`-Blöcke aus dem
|
||||||
|
PDF-Text rausnehmen. Echte aktive Inhalte stehen IMMER außerhalb
|
||||||
|
von Streams (in PDF-Object-Dictionaries) – Binär-Streams enthalten
|
||||||
|
Bilder/Fonts/Komprimiertes und werden jetzt zu Recht ignoriert.
|
||||||
|
- Smoke-Test: jspdf-Style-PDF mit `/JavaScript`-Bytes im Stream
|
||||||
|
durchgewinkt, echte `/OpenAction /S /JavaScript` weiterhin
|
||||||
|
blockiert, clean PDF weiterhin OK.
|
||||||
|
|
||||||
- [x] **🐞 AddressModal: Straße-Feld ließ sich nicht editieren**
|
- [x] **🐞 AddressModal: Straße-Feld ließ sich nicht editieren**
|
||||||
- `setFormData` wurde unbedingt im Render-Body aufgerufen, wenn
|
- `setFormData` wurde unbedingt im Render-Body aufgerufen, wenn
|
||||||
`formData.street !== address.street`. Jeder Tastendruck löste neu
|
`formData.street !== address.street`. Jeder Tastendruck löste neu
|
||||||
|
|||||||
Reference in New Issue
Block a user