Accept a password for encrypted OOXML files instead of terminating at `Encrypted`
- Dominant language
- Rust
- Stars
- 21.5k
- Forks
- 1.3k
- Avg merge
- 42m
- Merged PRs (30d)
- 17
Description
## 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`:
```rust
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 ` (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).*
Contributor guide
No contributing guide indexed for this repository
Research direction
Read src/package/archive.rs, especially probe_ole and the Format::from_bytes conversion path; then inspect the byte-level entry points and binding and CLI surfaces named by the issue. Check how existing errors and resource limits are propagated before settling the password API. Done means supplied-password OOXML reaches conversion, while missing or wrong passwords and out-of-scope encrypted formats retain Encrypted behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, python, rust, wasm
- Domain
- api, cli, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100