release: prepare OneNote Tools 0.2.0
This commit is contained in:
219
docs/SECURITY.md
219
docs/SECURITY.md
@@ -2,119 +2,172 @@
|
||||
|
||||
## 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.
|
||||
Selected `.one`, `.onepkg`, and companion `.cab` files are untrusted. The main
|
||||
thread validates the selection and combined size, reads the files into
|
||||
`ArrayBuffer`s, and transfers them to a dedicated module worker. 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.
|
||||
sandbox. A successful open keeps its session alive for page/resource/export
|
||||
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;
|
||||
- use a notebook-processing application backend, upload proxy, telemetry,
|
||||
analytics, remote fonts, or notebook-referenced external content fetching;
|
||||
the optional same-origin Toolbox catalogue/manifest is application chrome
|
||||
and receives no notebook data;
|
||||
- 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
|
||||
## Active parser defaults
|
||||
|
||||
The main thread rejects a source larger than 512 MiB before reading it. The
|
||||
OneStore section parsers then apply these independent defaults:
|
||||
The main thread accepts one `.one`, or one `.onepkg` plus its `.cab`
|
||||
companions. It permits at most 256 selected parts, 512 MiB per file, and 512 MiB
|
||||
combined before reading.
|
||||
|
||||
| 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 |
|
||||
| FSSHTTPB revision-chain entries | 16,384 |
|
||||
| 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 OneStore parser applies these independent defaults per section/store:
|
||||
|
||||
The CAB/package path applies these defaults:
|
||||
| Resource | Default limit |
|
||||
| ------------------------------------------------ | -------------------------: |
|
||||
| Section bytes | 512 MiB |
|
||||
| Transaction fragments / entries | 16,384 / 1,000,000 |
|
||||
| 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 |
|
||||
| FSSHTTPB revision-chain entries | 16,384 |
|
||||
| One property vector | 64 MiB |
|
||||
| Desktop object-reference vector | 1,000,000 per vector |
|
||||
| FSSHTTPB ExGUID/CellID references | 1,000,000 aggregate |
|
||||
| Nested PropertySets per ObjectPropSet | 1,000,000 aggregate |
|
||||
| File-data objects / one payload / total payloads | 10,000 / 256 MiB / 512 MiB |
|
||||
| Content-graph depth | 256 |
|
||||
| Content blocks / text runs / table cells | 100,000 each |
|
||||
| Decoded ink points | 100,000 |
|
||||
| Pages | 10,000 |
|
||||
| Diagnostics | 10,000 |
|
||||
| Retained rich/extracted text | 2,000,000 UTF-16 units |
|
||||
|
||||
| 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 |
|
||||
Images are automatically previewable only when a bounded PNG IHDR or JPEG
|
||||
marker/SOF inspection succeeds. The compressed payload must be at most 32 MiB,
|
||||
each dimension at most 16,384 pixels, and the image at most 67,108,864 pixels.
|
||||
JPEG inspection reads at most 1 MiB of markers and 4,096 marker records. Images
|
||||
outside those limits stay inert and are available only through an explicit
|
||||
download action.
|
||||
|
||||
The CAB/package path applies these defaults across a complete cabinet set:
|
||||
|
||||
| Resource | Default limit |
|
||||
| ------------------------------------------- | -----------------: |
|
||||
| One cabinet / complete set input | 512 MiB / 512 MiB |
|
||||
| Cabinet parts | 256 |
|
||||
| Folder segments / files | 1,024 / 10,000 |
|
||||
| CFDATA fragments | 131,072 |
|
||||
| CAB name bytes | 255 |
|
||||
| Path characters / path segments | 4,096 / 64 |
|
||||
| TOC construction operations / diagnostics | 1,000,000 / 10,000 |
|
||||
| One extracted file | 256 MiB |
|
||||
| One logical folder output | 512 MiB |
|
||||
| Total folder output / extracted entry bytes | 512 MiB / 512 MiB |
|
||||
| Logical-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.
|
||||
checksums; rejects overlapping/out-of-range data, traversal/absolute/control or
|
||||
case-insensitive duplicate paths; and validates a complete cabinet set before
|
||||
decoding. Set IDs, indexes, links, compression, split blocks, and spanning-file
|
||||
records must agree. Reserve areas are private to each cabinet/folder and are
|
||||
validated locally rather than compared across parts.
|
||||
|
||||
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. FSSHTTPB
|
||||
parsing bounds every declared stream body and compact integer, rejects invalid
|
||||
end markers and non-zero package tails, checks mapping/reference counts and
|
||||
revision cycles, and retains BLOB payloads as bounded source ranges. Fragment
|
||||
records are range-checked, but packages containing them are rejected because
|
||||
MSZIP checks `CK` framing and raw DEFLATE data, writes into a fixed caller
|
||||
buffer with overflow detection, requires the declared output size, and keeps at
|
||||
most 32 KiB of logical-folder history. LZX and Quantum validate their windows,
|
||||
trees/models, blocks/frames, matches, output, trailer, and operation budgets.
|
||||
Codec state is preserved across continued cabinet segments. Extraction checks
|
||||
cancellation between data blocks and periodically yields to the worker loop.
|
||||
|
||||
Desktop OneStore traversal checks fragment/reference cycles, nesting,
|
||||
object/property/reference counts, and byte ranges. FSSHTTPB parsing bounds every
|
||||
declared stream body and compact integer, rejects invalid end markers and
|
||||
non-zero package tails, checks aggregate reference/mapping counts and revision
|
||||
cycles, and retains BLOB payloads as bounded source ranges. Fragment records
|
||||
are range-checked, but packages containing them are rejected because
|
||||
fragmented-element reconstruction is not implemented.
|
||||
|
||||
## Rendering and links
|
||||
## Display and export budgets
|
||||
|
||||
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.
|
||||
Parser DTOs are projected through a smaller page-display budget before React
|
||||
creates nodes: 5,000 blocks, depth 64, 10,000 text runs, 500,000 displayed text
|
||||
units, 2,000 table rows, 5,000 table cells, 256 columns, 10,000 ink strokes,
|
||||
50,000 ink points, and 4,096 characters per metadata label. Exceeding a display
|
||||
budget produces an explicit truncation notice. Newlines remain inside text
|
||||
nodes instead of multiplying DOM elements.
|
||||
|
||||
## Known gaps and roadmap
|
||||
Navigation and inspectors separately expose at most 250 page links, 500
|
||||
notebook nodes at depth 16, 200 package entries per page, and 100 diagnostics
|
||||
per page. Titles, previews, package paths, diagnostic fields, and panel labels
|
||||
are length-bounded; pagination/truncation remains explicit in the UI.
|
||||
|
||||
- There is no wall-clock deadline. Synchronous OneStore `.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.
|
||||
Export planning independently permits at most 10,000 sections, 100,000 pages,
|
||||
1,000,000 blocks, depth 256, 100,000 diagnostics, 8,000,000 text units, and
|
||||
500,000 ink points. One resource and all resources are capped at 64 MiB; one
|
||||
standalone output or all uncompressed static-ZIP members are capped at 128 MiB.
|
||||
Planning accounts for metadata and projected UTF-8 output before serialization,
|
||||
then verifies actual encoded/member sizes. Resource views remain zero-copy until
|
||||
the bounded serializer needs bytes.
|
||||
|
||||
## Rendering, links, and downloads
|
||||
|
||||
DTO strings are rendered as React text nodes. Notebook HTML, scripts, active
|
||||
SVG, and attachment payloads are never injected. Only parsed ink coordinates
|
||||
generate application-owned SVG path attributes. Hyperlinks require an explicit
|
||||
click, are limited to `http`, `https`, or `mailto`, and use
|
||||
`rel="noopener noreferrer"`.
|
||||
|
||||
Automatic image requests carry a distinct preview intent. The worker rejects a
|
||||
non-image, unapproved media type, unsafe dimensions, or oversized payload before
|
||||
allocating/copying its bytes to the main thread. Approved image bytes may cross
|
||||
for automatic preview; attachment bytes and rejected image bytes cross only
|
||||
after the user presses a download button.
|
||||
|
||||
Static export HTML is inert, contains no script or external fetch, escapes all
|
||||
text/attributes, embeds only images that pass the same inspector, and
|
||||
neutralizes potentially active attachment suffixes. Exports represent the
|
||||
supported reader model; they do not write OneNote files.
|
||||
|
||||
## Known gaps
|
||||
|
||||
- There is no wall-clock deadline. Synchronous OneStore graph parsing cannot
|
||||
observe cancellation until control returns; terminating the worker is the
|
||||
current hard stop.
|
||||
- Package opening can hold source cabinets, decompressed logical folders,
|
||||
extracted entry views, and parsed DTOs at overlapping times. Byte/count limits
|
||||
bound them, but do not guarantee a low peak heap.
|
||||
- Section content limits apply per contained section rather than once to the
|
||||
complete `.onepkg`; cabinet/TOC limits are aggregate for the package set.
|
||||
- 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
|
||||
- Format coverage is limited to the documented golden files and structures.
|
||||
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.
|
||||
Planned hardening includes elapsed-time budgets, more cancellation checkpoints,
|
||||
lower-peak-memory extraction, expanded malformed-input/fuzz corpora, fragmented
|
||||
FSSHTTP reconstruction, and additional licensed OneNote producer fixtures.
|
||||
|
||||
## Fixtures and vulnerability reporting
|
||||
|
||||
|
||||
Reference in New Issue
Block a user