122 lines
6.2 KiB
Markdown
122 lines
6.2 KiB
Markdown
# 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.
|