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.
Summary
Extractor().extract_file_to_string()fails withTIKA-198: Illegal IOException from org.apache.tika.parser.epub.EpubParseron 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 withwriter2epub 1.1.28. The structural pattern:The OPF manifest declares the root-level
toc.xhtmlwith a parent reference:And the spine/nav also points to
../toc.xhtml#calibre_generated_inline_toc. Tika'sEpubParserrejects the path-traversal ref and throwsIOException, surfacing as TIKA-198.Minimal Python repro:
Root cause
Tika's
EpubParserrefuses 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 iniscc-sdkalso other tools) emit../foo.xhtmlreferences 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-sdktext/EPUB pipeline (iscc_sdk/text.py:114, callsExtractor().extract_file_to_string)In
iscc-sdkwe 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/srcvalues 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).2. Java-side patch to
EpubParserTolerate
../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.