// Import-path resource bounds — audit fixes MV-4 (decompression bomb) and // MV-5 (unbounded file/string allocation). // // Every untrusted import surface (pasted PeachScript/backup strings, .peach / // .json files, Codex PDFs) must check these BEFORE allocating or inflating. export const IMPORT_LIMITS = { /** Hard ceiling on any decompressed output (zstd sections, pako inflate). */ MAX_DECOMPRESSED_BYTES: 64 * 1024 * 1024, // 64 MiB /** Ceiling on an attacker-declared pre-decompress length field. */ MAX_DECLARED_LENGTH: 64 * 1024 * 1024, // 64 MiB /** Max PDF file size accepted by the Codex importer. Current-generation * Codexes (350-byte chunks) run far more pages for the same vault — real * ones exceed 40 MiB. Render memory is bounded separately by the page * dimension and page-count caps in pdf-import.ts, not by file size. */ MAX_PDF_BYTES: 64 * 1024 * 1024, // 64 MiB /** Max raw JSON/CSV/PeachScript string length accepted by import/restore. */ MAX_JSON_BYTES: 10 * 1024 * 1024, // 10 MiB /** * Max entries one parse may yield. A 10 MiB input of minimal rows expands to * ~25x its size in ImportableEntry objects, which is enough to kill an MV3 * service worker. Matches the sync layer's MAX_ENTRY_COUNT. */ MAX_IMPORT_ENTRY_COUNT: 100_000, } as const; /** * Error code shared by all import-path size rejections. The import UI maps * it to a user-readable message ("This file is too large to be a Peach * backup …") instead of surfacing a raw thrown error. */ export const IMPORT_TOO_LARGE = "IMPORT_TOO_LARGE"; export function importTooLarge(detail: string): Error { return new Error(`${IMPORT_TOO_LARGE}: ${detail}`); }