Skip to content

EPUB extraction fails with TIKA-198 when OPF manifest uses '../' path traversal #6

Description

@titusz

Summary

Extractor().extract_file_to_string() fails with TIKA-198: Illegal IOException from org.apache.tika.parser.epub.EpubParser on otherwise-valid EPUBs whose OPF manifest references files outside the OPF's directory using ../ path segments.

Reproduction

Encountered via iscc-sdk (iscc_tika 0.4.0) on a real-world EPUB authored with writer2epub 1.1.28. The structural pattern:

mimetype
toc.xhtml                         <- at zip root
META-INF/container.xml            <- points to OEBPS/content.opf
OEBPS/content.opf
OEBPS/text/content0001.xhtml
...

The OPF manifest declares the root-level toc.xhtml with a parent reference:

<item href="../toc.xhtml" id="id" media-type="application/xhtml+xml"/>

And the spine/nav also points to ../toc.xhtml#calibre_generated_inline_toc. Tika's EpubParser rejects the path-traversal ref and throws IOException, surfacing as TIKA-198.

Minimal Python repro:

from iscc_tika import Extractor
Extractor().extract_file_to_string('path/to/book.epub')
# TypeError: ParseError("Parse error occurred : TIKA-198: Illegal IOException
# from org.apache.tika.parser.epub.EpubParser@...")

Root cause

Tika's EpubParser refuses zip entries that resolve outside the OPF directory — a defensible security stance against zip path traversal. But some authoring tools (writer2epub here, and per prior triage in iscc-sdk also other tools) emit ../foo.xhtml references that resolve to a real entry inside the same zip. Mainstream EPUB readers tolerate this; Tika does not.

This makes the failure look like a data-integrity error to callers, when in practice the file is recoverable.

Affected callers

  • iscc-sdk text/EPUB pipeline (iscc_sdk/text.py:114, calls Extractor().extract_file_to_string)
  • Likely anything else routing EPUBs through iscc-tika

In iscc-sdk we see this on multiple real-world fixtures (e.g. files from streetlib catalog, and the one that triggered this issue: 9781365886386.epub).

Suggested fixes

Two approaches, in order of preference:

1. Pre-parse repair shim in iscc-tika (preferred)

Before invoking Tika, detect manifest/spine href/src values whose normalized resolution escapes the OPF directory but matches an entry that exists elsewhere in the zip. Rewrite the OPF in a temp copy so the references resolve inside the OPF directory (either by relocating the target entries or by rewriting the path strings).

  • Self-contained, ~30 lines on the Python binding side
  • Preserves Tika's path-traversal protection for genuinely malicious inputs
  • One fix benefits every iscc-tika consumer

2. Java-side patch to EpubParser

Tolerate ../ segments when the resolved path stays within the zip root. Closer to the root cause, but heavier maintenance — requires touching the GraalVM-built Tika bundle.

Happy to help

I can prototype the pre-parse repair shim (option 1) if useful — it would live in the Python binding's pre-processing step and would only kick in when iscc-tika detects path-traversal entries in the OPF.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions