# Parser Dependency Audit
Audit date: 2026-07-25 UTC.
## Boundary
`kcode-doc-extraction` gives parser dependencies only caller-supplied in-memory
bytes and no credentials. The crate performs no network, filesystem, shell, or
subprocess access. It enforces its input byte limit before invoking a parser.
Async callers must place extraction on a blocking worker.
`pdf-extract` parses searchable PDF text, `zip` and `quick-xml` parse DOCX, and
`calamine` parses supported workbooks. Their prior audit remains unchanged.
## Legacy Word dependency
Version 0.2.0 adds the exact crates.io dependency `unword = "=0.2.0"` for
Word 97-2003 binary `.doc` files.
Registry evidence:
- crates.io published 0.2.0 on 2026-03-23 under the MIT license.
- The published checksum is
`d5032cbecb14e09b81b29f759733bb305b9e19c62da009213d9f7741528ed856`.
- The package declares Rust edition 2021 and no minimum supported Rust version.
Compatibility with this crate's Rust 1.97 policy is established by this
crate's release check rather than upstream metadata.
- The published package has 793 lines of Rust code across ten files.
- Direct dependencies are `anyhow` 1, `cfb` 0.14, `clap` 4 with `derive`, and
`encoding_rs` 0.8. Optional Python support uses `pyo3` and is disabled by
default. `clap` and `anyhow` are unconditional upstream dependencies; their
build cost is accepted for this small first integration.
- Inspection of the complete published library source found no `unsafe` block
or `unsafe` declaration. This does not make its transitive parser stack a
hostile-input sandbox.
The upstream repository contains later tag 0.2.2, but crates.io exposes only
0.2.0. This crate deliberately stays within crates.io and does not use the Git
tag or the similarly numbered Python release.
## Behavior reviewed
`unword::parse_doc_with_options(&[u8], true)` reads the OLE/CFB
`WordDocument` and selected table stream, parses FIB and CLX records, extracts
compressed Windows-1252 or UTF-16 text, maps a subset of paragraph styles to
Markdown headings, strips field instructions while retaining visible field
results, and returns body text, textboxes, and separate field metadata.
This crate keeps the readable body text, appends nonempty textboxes in the
parser-returned order, and ignores separate field metadata. It does not execute
macros or fields, resolve links, extract embedded OLE objects, preserve visual
layout, or promise complete Word-format fidelity.
## Malformed-input review and containment
The published parser is young and has unchecked malformed-input paths. In
particular, document-controlled FIB offsets can reach unchecked indexing; CLX
parsing can form an unchecked slice and subtract four from an untrusted length;
and PAPX parsing derives offsets from untrusted counts. These paths can panic.
Parser-owned allocations and CFB processing also mean this dependency is not a
strict CPU or memory boundary.
For the current baseline release:
- the existing 20 MiB default input limit applies before parsing;
- `catch_unwind` contains ordinary unwinding parser panics;
- parser errors and caught panics become sanitized `ExtractionFailed` errors;
- upstream parser text is not exposed to callers;
- focused tests cover random bytes, a truncated valid fixture, ZIP-like bytes,
and repeated arbitrary bytes without allowing a panic to escape.
This baseline does not contain process aborts, out-of-memory conditions,
pathological CPU use, bugs in native or transitive dependencies, or other
process-level failures. Before treating hostile legacy documents as strongly
isolated, run a broader mutation/fuzz corpus and move parsing behind a bounded
worker process or equivalent memory, CPU, timeout, and crash boundary. That is
deferred work, not a claim of this release.
## Test fixture
Tests construct a deterministic OLE/CFB document entirely in memory with the
MIT-licensed `cfb = "=0.14.0"` development dependency. The fixture supplies the
minimum streams and Word records needed by the selected parser and exercises
Unicode body text, field-code stripping, multiple textboxes, empty text,
character truncation, pre-parse byte limits, and malformed/truncated input.
The generated fixture is a wrapper-level regression aid, not an independent
implementation of Microsoft Word, broad real-world compatibility evidence, or
a substitute for later corpus and fuzz testing. Parser dependency changes
require source, license, malformed-input, fixture, and package-content review
before publication.