mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-26 03:17:28 -06:00
* Harden against hostile-document DoS and non-web link export A security pass found several small files that make the app allocate or compute without bound when opened (GUI, wordcraft-cli, or the MCP server), and link targets leaving on export without the scheme check the HTML and Markdown writers already apply. None lets a document run code or read files; all are denial-of-service or credential-leak-on-click. Each fix bounds an attacker-controlled size and lands with a regression test, per the never-crash standard. - layout: a table repeats its header rows on every page it spills onto, so many tall header rows paginate to O(headers x pages) placed items. Cap the total header-row repeats per table (lib.rs). 2 KB docx: 1.1 GB -> 124 MB. - formats/model, html: an HTML table of many <tr> with large rowspan expanded to rows x 64 covered cells, and `model::table` pre-allocated a full rows x cols grid only to clear it. Cap rows at MAX_ROWS before insert_covered, bound its total work, and build the grid template with one row. 640 KB html: >1.5 GB -> 214 MB (a plain large table is faster too). - docx/read/freeform: a custom-geometry Bezier segment took any number of points, making de Casteljau flattening quadratic. Cap points per segment. 3 KB docx: 12 s -> 0.15 s. - docbin: footnote/header/text-box story tables and the piece table can name the same backing text many times. Hold the total characters materialised to twice the WordDocument stream size (a ceiling no real file reaches, since each char costs >=1 stream byte). 45 KB doc: >1.2 GB -> 14 MB. - render, pdf, formats/rtf: document pictures were decoded with no dimension limit, so a tiny file declaring a huge image could allocate before the size check. Decode through image::Limits with a side cap first. - doc/link, formats/rtf, odt, latex: route exported hyperlink targets through is_safe_href (as HTML/Markdown already do), and extend it to reject protocol-relative (//host) and UNC (\host) references. Keeps file:, javascript:, ms-msdt: and UNC targets from being written into exported RTF, ODT, LaTeX and PDF where a reader would follow them (UNC leaks NTLM on Windows). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Align picture-decode limits with the bounds already in force Review of the previous commit: `image::load_from_memory` and `load_from_memory_with_format` already applied `Limits::default()`, whose 512 MB allocation cap bounded every picture decode. The PDF change had set `max_alloc = None`, loosening that; restore the default. The render and RTF side caps (16 384 px) newly rejected wide-but-short pictures that fit in memory, so render now uses the pixmap's own `u16` side limit (what `premul_pixmap` enforced after decoding, applied before it instead) and the RTF re-encode keeps only the explicit allocation cap. Net effect: rejection moves to header time with no change to the sizes accepted. Also fix a comment: the header-row repeat cap is per table, not per document. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>