Summary
A password-protected .xlsx/.docx/.pptx always ends in ConvertError::Encrypted, and there is no way to supply the password. The rejection is precise and deliberate today: probe_ole (src/package/archive.rs) identifies the OLE container with EncryptionInfo/EncryptedPackage streams and returns Encrypted.
For a caller that has the password, the file is still unconvertible.
Why this matters
Document-ingestion pipelines (the LLM/RAG use case the README targets) receive password-protected spreadsheets and documents routinely, and the password is usually known: it arrived alongside the file.
Rust users can already work around this by composing the office-crypto crate with to_markdown_bytes:
let decrypted = office_crypto::decrypt_from_bytes(std::fs::read(path)?, "secret")?;
let md = anydoc::to_markdown_bytes(&decrypted, None)?;
But Node, Python, wasm, and CLI users have no equivalent: there is no solid OOXML-decryption library on those sides, so for the bindings the file is a dead end.
Proposed shape (narrowest version)
- An optional password on the byte-level entry points, e.g.
to_markdown_bytes(bytes, format, password: Option<&str>) or _with_password variants, mirrored in the bindings.
- CLI:
--password <pw> (plus perhaps an env-var fallback, since argv leaks into shell history and ps).
- Where
probe_ole currently returns Encrypted: if a password was supplied, decrypt via office-crypto and re-enter Format::from_bytes -> conversion with the plaintext. All existing resource limits then apply to the decrypted package unchanged. No password supplied, or wrong password: Encrypted, exactly as today.
office-crypto (v0.3.0) is pure Rust, its dependencies are all RustCrypto crates plus quick-xml (already a dependency here), and decryption needs no randomness, so the wasm target should be unaffected. Decryption cost is milliseconds.
Out of scope
- Legacy encrypted
.xls/.ppt (RC4 CryptoAPI): not supported by office-crypto; would keep returning Encrypted.
- Encrypted ODF: a different scheme entirely; would keep returning
Encrypted.
This issue was written with AI assistance (Claude Fable 5).
Summary
A password-protected
.xlsx/.docx/.pptxalways ends inConvertError::Encrypted, and there is no way to supply the password. The rejection is precise and deliberate today:probe_ole(src/package/archive.rs) identifies the OLE container withEncryptionInfo/EncryptedPackagestreams and returnsEncrypted.For a caller that has the password, the file is still unconvertible.
Why this matters
Document-ingestion pipelines (the LLM/RAG use case the README targets) receive password-protected spreadsheets and documents routinely, and the password is usually known: it arrived alongside the file.
Rust users can already work around this by composing the
office-cryptocrate withto_markdown_bytes:But Node, Python, wasm, and CLI users have no equivalent: there is no solid OOXML-decryption library on those sides, so for the bindings the file is a dead end.
Proposed shape (narrowest version)
to_markdown_bytes(bytes, format, password: Option<&str>)or_with_passwordvariants, mirrored in the bindings.--password <pw>(plus perhaps an env-var fallback, since argv leaks into shell history andps).probe_olecurrently returnsEncrypted: if a password was supplied, decrypt viaoffice-cryptoand re-enterFormat::from_bytes-> conversion with the plaintext. All existing resource limits then apply to the decrypted package unchanged. No password supplied, or wrong password:Encrypted, exactly as today.office-crypto(v0.3.0) is pure Rust, its dependencies are all RustCrypto crates plusquick-xml(already a dependency here), and decryption needs no randomness, so the wasm target should be unaffected. Decryption cost is milliseconds.Out of scope
.xls/.ppt(RC4 CryptoAPI): not supported by office-crypto; would keep returningEncrypted.Encrypted.This issue was written with AI assistance (Claude Fable 5).