Skip to content

Tika Python 3.4.0 release

Latest

Choose a tag to compare

@chrismattmann chrismattmann released this 09 Nov 21:54
· 6 commits to master since this release
e11d8c7

This is a security release. If you run tika-python on Linux or in a container on a host where other accounts exist, upgrade.

pip install --upgrade tika

Local code execution through the server jar cache

tika-python downloads tika-server.jar and runs it. Before this release it cached that jar at a predictable path in the shared temp directory — /tmp/tika-server.jar on Linux — and verified it against a checksum file at an equally predictable path beside it, /tmp/tika-server.jar.md5. The real checksum was fetched only when that local file did not exist.

So another local user could create both files before your first parse, and their jar would be validated against their own checksum and then executed under your account. The sticky bit on /tmp does not prevent it: nothing is being overwritten, the attacker simply gets there first — in practice, first after a boot or a /tmp cleanup.

The hash algorithm was not the weakness. Setting TIKA_JAR_HASH_ALGO=sha512 left the bypass fully intact, because the digest was still read from a file the same attacker could write.

Four related defects are fixed in the same change:

  • The verification failure path ran the jar anyway. On a mismatch the old code deleted the jar, downloaded it again, and started the second copy without checking it. It also never cleared the stale checksum, so a planted checksum on its own — no jar needed — forced a 76 MB re-download on every call.
  • The default download was plaintext http://, from search.maven.org rather than the canonical repository. The jar and the checksum beside it both travelled in the clear, so substituting them required no local account at all.
  • /tmp/tika-server.log was opened for truncation and /tmp/tika.log for append, both at predictable names — a symlink planted at either was a way to blank or append to any file you could write.
  • Documents fetched from URLs were written into the shared directory under predictable names.

Who was affected

Primarily Linux and containers, where tempfile.gettempdir() is /tmp (mode 1777). On macOS the default temp directory is already a per-user 0700 directory under /var/folders, so macOS users were largely not exposed. Windows puts per-user temp directories under the profile.

If you cannot upgrade yet

Point the cache at a private directory: export TIKA_PATH=~/.cache/tika and export TIKA_LOG_PATH=~/.cache/tika, with the directory created mode 0700. Or run with TIKA_CLIENT_ONLY=True against a server you start yourself.

How verification works now

  • The expected SHA-512 ships in the package, keyed by Tika version, so verifying the jar depends on neither the network nor anything on local disk. The 3.3.2 entry is the artifact signed by ASF release key 184454FAD8697760F3E00D2E4A51A45B944FFD51, checked against Apache's KEYS.
  • A digest is never written to disk. For a Tika version with no pinned entry, or a custom TIKA_SERVER_JAR, the published digest is fetched over https into memory only, strongest first, and refused outright over plaintext where it would prove nothing.
  • Verification failure raises instead of starting anything.
  • Downloads land on a pid-unique temporary name, are verified, and only then moved into the path that gets executed — so a wrong or half-written jar is never at the name that runs.
  • The cache defaults to a per-user directory created 0700: ~/.cache/tika, ~/Library/Caches/tika, or %LOCALAPPDATA%\tika.
  • Every cache file is opened with O_NOFOLLOW and refused if it is owned by another user or writable by others — so pointing TIKA_PATH back at a shared directory is still safe.

Upgrade notes

This is a minor rather than a patch release because some behaviour changes:

Change What to expect
The jar cache moved out of the temp directory The server jar is downloaded once more, into the new per-user cache. An old /tmp/tika-server.jar is reported as unused and left alone — it is safe to delete, along with its .md5.
TIKA_JAR_HASH_ALGO is ignored It never provided the protection it appeared to. Setting it now logs a warning explaining why.
Verification failure raises RuntimeError Previously the server was started regardless. A jar that cannot be verified no longer runs.
checkJarSig no longer reads a .md5 sidecar If you called it directly, it now compares against the pinned or published digest.
parseAndSave with no outDir now writes files It previously computed a path, wrote nothing, and returned the name of a file that did not exist. It now writes <input>_meta.json next to each input, as its name and docstring always said.

New environment variables

  • TIKA_SERVER_JAR_SHA512 — expected digest for a private or unpinned jar build.
  • TIKA_FILES_PATH — where documents fetched from URLs are written.

Also in this release

  • uv run --group tests could not resolve the project on Python 3.10 or 3.11: a documentation dependency (sphinx>=9.1, which needs 3.12+) was taking the test group down with it under uv's universal resolution. The docs dependencies are now marked for the Python they require. requires-python stays >=3.10.
  • The release script no longer uploads whatever was left in dist/ from the previous release, and runs twine check before publishing anything.
  • Test suite grew from 28 to 78 cases; coverage of tika/tika.py rose from roughly 49% to 65%.

Full changelog: 3.3.2...3.4.0