# Security model ## Trust boundary and local processing Selected `.one` and `.onepkg` files are untrusted. The main thread checks the source size, reads one file into an `ArrayBuffer`, transfers it to a dedicated module worker, and receives serializable data-transfer objects. CAB entries are extracted only into memory; archive paths are never written to the filesystem. The worker is a fault-containment and responsiveness boundary, not a security sandbox. A successful open keeps its worker session alive for page requests. Clearing the file, choosing another file, or unmounting the app terminates that worker; a failed open also terminates it. JavaScript garbage collection does not promise immediate release or secure erasure. The application does not: - upload or transmit notebook bytes; - use a backend, proxy, telemetry, analytics, remote fonts, or external content fetching; - persist source or derived content in LocalStorage, IndexedDB, Cache Storage, cookies, or a service worker; - execute notebook content or inject notebook HTML/SVG; - use WebAssembly, a Rust runtime, or a native helper. ## Active default limits The main thread rejects a source larger than 512 MiB before reading it. The desktop section parser then applies these independent defaults: | Resource | Default limit | | ------------------------------------- | -------------------: | | Section bytes | 512 MiB | | File-node list fragments / nesting | 16,384 / 64 | | File nodes | 1,000,000 | | Objects | 500,000 | | Properties per set / property nesting | 16,384 / 64 | | Stream IDs | 1,000,000 | | One property vector | 64 MiB | | Object references | 1,000,000 | | Content-graph depth | 256 | | Pages per section | 100,000 | | Diagnostics per section | 10,000 | | Extracted text per section | 2,000,000 characters | The CAB/package path applies these defaults: | Resource | Default limit | | ------------------------------- | -------------: | | Cabinet input | 512 MiB | | Folders / files | 1,024 / 10,000 | | CFDATA blocks | 131,072 | | CAB name bytes | 255 | | Path characters / path segments | 4,096 / 64 | | One extracted file | 256 MiB | | One folder output | 512 MiB | | Total folder output | 512 MiB | | Total extracted entry bytes | 512 MiB | | Folder compression ratio | 200:1 | | One MSZIP compressed block | 32 KiB + 12 B | | Quantum window | 2 MiB | | LZX window | 8 MiB | | LZX/Quantum decode operations | 1,000,000,000 | A CFDATA block may declare at most 32 KiB of output. Counts and offsets use checked arithmetic and bounded readers. The CAB parser verifies supplied block checksums, rejects overlapping/out-of-range data, rejects absolute/traversal, empty, control-character, and case-insensitive duplicate paths, and refuses multi-cabinet/spanning entries. MSZIP checks its `CK` framing and raw DEFLATE data, writes into a fixed caller buffer with one overflow-detection byte, requires the exact declared output size, and retains no more than 32 KiB of history. LZX checks its window, Huffman trees, block sizes, match ranges, output size, and operation budget. CAB Quantum limits its window, model scans, arithmetic renormalisation, matches, frame/output boundaries, operation count, and trailer padding. It queues at most the current and next compressed block so a synthetic `0xFF` sentinel can be consumed without buffering a complete folder. CAB extraction checks cancellation during Quantum work and yields between data blocks so the worker can process termination. Desktop OneStore traversal checks fragment/reference cycles, nesting, object/property/reference counts, and byte ranges. ## Rendering and links DTO strings are rendered as React text nodes. Notebook HTML, active SVG, scripts, attachment payloads, and automatic external navigation are not rendered. Link activation is not implemented. If links are added, they require explicit user action, scheme validation, and safe navigation attributes. ## Known gaps and roadmap - There is no wall-clock deadline. Synchronous desktop `.one` parsing cannot observe cooperative cancellation until control returns; terminating the worker is the current hard stop. - The package flow holds the source, decompressed folder buffers, extracted entry slices, and parsed DTOs in memory at overlapping times. The byte/count limits bound these individually but do not guarantee a low peak heap. - Section text/page/diagnostic limits apply per contained section rather than once to the complete package. - CAB checksums detect accidental corruption but do not authenticate a package. - Format coverage is narrow and has only the documented golden files. New producer/version claims require licensed regression fixtures and malformed variants. - The worker boundary reduces UI impact but is not a substitute for browser and operating-system isolation. Open especially sensitive files in a dedicated browser profile if that risk matters. Planned hardening includes an elapsed-time budget, cancellation checkpoints in desktop OneStore graph traversal, aggregate package DTO/text budgets, lower peak-memory extraction, expanded malformed-input/fuzz corpora, and additional licensed OneNote export fixtures. ## Fixtures and vulnerability reporting Never commit private notebooks. Fixture provenance and redistribution terms must be recorded in `tests/fixtures/README.md`. Report suspected parser vulnerabilities privately to the repository owner through the Gitea instance before publishing malicious fixtures. Include the application version, browser, smallest reproducible input, diagnostic, and observed resource use. Do not attach sensitive notebooks.