Skip to content

feat: accept passwords for encrypted OOXML files - #103

Open
patriksimms wants to merge 3 commits into
firecrawl:mainfrom
patriksimms:feat/ooxml-password-102
Open

patriksimms wants to merge 3 commits into
firecrawl:mainfrom
patriksimms:feat/ooxml-password-102

Conversation

@patriksimms

@patriksimms patriksimms commented Aug 16, 2026 •

Copy link
Copy Markdown

Problem

Callers who know the password for an encrypted Office document cannot convert it through anydoc's bindings or CLI.

Solution

Decrypt encrypted OOXML before detecting and parsing its inner format. Expose optional passwords in Rust, Node, Python, and Wasm, plus --password and ANYDOC_PASSWORD in the CLI. Node Markdown functions accept options.password alongside the existing OCR options; Python Markdown functions accept password=. Existing calls keep their behavior.

Closes #102

Validation

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --locked: 302 passed; one local-samples test ignored
  • Node release build and all 25 tests passed
  • Python release wheel build and all 14 tests passed
  • Real encrypted Excel fixture checked against its expected cell values and text
  • Independently encrypted a real Excel workbook with msoffcrypto-tool; decrypted Python output matched the original workbook exactly, including dates, currency, percentages, and merged cells
  • CLI converted the independently encrypted workbook from both a file and stdin with an explicit XLSX format; missing and wrong Excel passwords returned encrypted errors
  • Extensionless and .bin-renamed encrypted Excel files convert; the regression failed before the fix and passes afterward
  • Focused independent Standards and Spec delta reviews of 67933fa..f78a00b found no blockers; no initial full-review baseline was supplied
  • Wasm crate passed workspace Clippy on the host; Wasm build and execution remain for CI because the local target is unavailable

Changes were made with openai/gpt-6.1-sol through the Codex harness in T3 Code.

Summary:
- decrypt password-protected OOXML before format detection and conversion
- expose optional passwords through Node, Python, wasm, and the CLI
- cover successful, missing, and incorrect password behavior with fixtures

Rationale:
- callers with a known password can now convert encrypted Office files
  without changing the existing behavior for callers without one
- explicit Rust variants preserve compatibility with existing signatures

Tests:
- cargo fmt --all --check
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo test --locked
- npm run build && npm test (node)
- maturin build --release --locked and Python unit tests

Closes firecrawl#102

AI-Assisted: true
AI-Agent: codex
AI-Model: openai/gpt-5.6-sol
Merge upstream main and resolve conflicts while keeping password support
alongside the new hosted OCR wrappers and CLI options.

Use office-crypto 0.4.0, whose published crypto.rs and ole.rs match the
malformed-container fixes in udbhav1/office-crypto#7. Forward passwords
through the public Node and Python wrappers, and add a regression for
an oversized encrypted package declaration.

Validation:
- cargo fmt --all --check
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo test --locked: 302 passed, one local-samples test ignored
- Node release build and all 24 tests passed
- Python release wheel build and all 14 tests passed
- Independently encrypted a real Excel workbook with msoffcrypto-tool;
  Python output matched the original workbook exactly
- CLI converted that workbook from a path and stdin; missing and wrong
  Excel passwords returned encrypted errors

Wasm target execution remains for CI; this machine lacks the target.

Related to firecrawl#103 and udbhav1/office-crypto#7.

AI-Assisted: true
AI-Agent: codex
AI-Model: openai/gpt-6.1-sol
@patriksimms
patriksimms marked this pull request as ready for review November 6, 2026 09:13

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 26 files

Reply to a comment to ask cubic a question or push back. It learns from your replies.
Click Fix with cubic on a comment, or reply @cubic-dev-ai fix this, and cubic writes the fix.

View guided diff | Re-trigger cubic

Comment thread node/README.md Resolved
Comment thread tests/passwords.rs Resolved
Comment thread src/lib.rs Resolved
Comment thread src/lib.rs Resolved
Comment thread wasm/test.mjs Resolved
Comment thread wasm/src/lib.rs Resolved
Comment thread python/src/lib.rs Resolved
Comment thread python/anydoc/__init__.py Resolved
Probe encrypted containers before rejecting a path without a recognized
extension, so password-based conversion works for renamed workbooks.
Keep encrypted errors for unrecognized decrypted bytes because
 office-crypto can return garbage rather than an error for wrong passwords.

Clarify the OOXML password docs, exercise Python and Wasm document-model
password forwarding, and use valid encryption metadata and ciphertext in
the oversized-length fixture so only the declared size is malformed.

Validation:
- New Node path regression failed before the fix and passes afterward
- cargo fmt --all --check
- cargo clippy --workspace --all-targets --all-features -- -D warnings
- cargo test --locked: 302 passed, one local-samples test ignored
- Node release build and 25 tests passed
- Python release wheel build and 14 tests passed
- Verified malformed fixture differs from valid DOCX only in its package
  length field; Wasm target execution remains pending CI

Related to firecrawl#103.

AI-Assisted: true
AI-Agent: codex
AI-Model: openai/gpt-6.1-sol

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Accept a password for encrypted OOXML files instead of terminating at Encrypted

1 participant