Files
paperlessmanager/paperless-backend/src/email/pdf-fingerprint.bombe.spec.ts
T
bjoernpoettkerandClaude Opus 5.5 de9cb09bcd fix(security): Ghostscript mit -dSAFER, Schutz vor PDF-Dekompressionsbomben
- Ghostscript läuft auf PDFs aus Mails und vom Scanner jetzt mit -dSAFER
  statt -dNOSAFER (kein Datei-/Prozesszugriff aus PostScript), mit
  Timeout (60 s je Seite, 10 min je Dokument, SIGKILL) und höchstens
  500 gerenderten Seiten. Temp-Dateien werden auch im Fehlerfall
  entfernt. Ungenutztes getPageCount (brauchte Dateizugriff) entfernt.
- Neuer Vorab-Check ueberschreitetDekompressionsLimit (256 MB, streamend,
  erkennt auch Deflate-Ketten und abgeschnittene Streams). Fingerprint
  (pdf.js) und E-Rechnungs-Extraktion (pdf-lib) laden Bomben nicht mehr;
  eine einzelne Mail konnte das Backend sonst per OOM dauerhaft lahmlegen.
- Verschlüsselte PDFs bekommen keinen Inhalts-Fingerprint mehr ('' =
  nicht vergleichbar), weil pdf.js sie erst intern entschlüsselt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 10:46:43 +01:00

32 lines
1.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import * as zlib from 'zlib';
import { PDFParse } from 'pdf-parse';
import { computeContentFingerprint } from './pdf-fingerprint.util';
jest.mock('pdf-parse', () => ({ PDFParse: jest.fn() }));
describe('computeContentFingerprint – ungeprüfte Inhalte', () => {
it('übergibt eine Deflate-Bombe nicht an pdf.js', async () => {
const bombe = zlib.deflateSync(Buffer.alloc(300 * 1024 * 1024));
const pdf = Buffer.concat([
Buffer.from(
`%PDF-1.7\n1 0 obj\n<< /Length ${bombe.length} /Filter /FlateDecode >>\nstream\n`,
'latin1',
),
bombe,
Buffer.from('\nendstream\nendobj\n%%EOF\n', 'latin1'),
]);
await expect(computeContentFingerprint(pdf)).resolves.toBe('');
expect(PDFParse).not.toHaveBeenCalled();
});
it('übergibt verschlüsselte PDFs nicht an pdf.js', async () => {
const pdf = Buffer.from(
'%PDF-1.7\ntrailer\n<< /Encrypt 5 0 R >>\n%%EOF\n',
'latin1',
);
await expect(computeContentFingerprint(pdf)).resolves.toBe('');
expect(PDFParse).not.toHaveBeenCalled();
});
});