Package: calibre Version: 8.5.0+ds-1+deb13u3 Severity: important Dear Maintainer,
ebook-convert fails on every EPUB that uses font obfuscation and reports the file as DRM-protected, although such files carry no DRM. The cause is a NameError for is_existing_subpath in calibre/ebooks/conversion/plugins/epub_input.py. The affected code is the guard added for CVE-2026-25636. Its call site is present in this package, but neither the import nor the two helper functions it depends on are, so the guard raises NameError every time it is reached. Steps to reproduce ------------------ Convert any EPUB whose META-INF/encryption.xml declares font obfuscation, that is, an EncryptionMethod with one of Algorithm="http://www.idpf.org/2008/embedding" (IDPF obfuscation) Algorithm="http://ns.adobe.com/pdf/enc#RC" (Adobe obfuscation) Font obfuscation only mangles the embedded font files so they cannot be extracted and reused directly; it is not a DRM scheme and is common in commercially published EPUBs. Such a file can be built from any EPUB with an embedded font by adding a META-INF/encryption.xml that names that font's path in a CipherReference URI. $ ebook-convert book.epub /tmp/out.txt Actual result ------------- 1% Converting input to HTML... InputFormatPlugin: EPUB Input running on book.epub Traceback (most recent call last): File "/usr/lib/calibre/calibre/ebooks/conversion/plugins/epub_input.py", line 79, in process_encryption if (tkey and is_existing_subpath(path, container_base)): ^^^^^^^^^^^^^^^^^^^ NameError: name 'is_existing_subpath' is not defined Traceback (most recent call last): File "/usr/bin/ebook-convert", line 21, in <module> sys.exit(main()) ~~~~^^ File "/usr/lib/calibre/calibre/ebooks/conversion/cli.py", line 429, in main plumber.run() ~~~~~~~~~~~^^ File "/usr/lib/calibre/calibre/ebooks/conversion/plumber.py", line 1089, in run self.oeb = self.input_plugin(stream, self.opts, ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ self.input_fmt, self.log, ^^^^^^^^^^^^^^^^^^^^^^^^^ accelerators, tdir) ^^^^^^^^^^^^^^^^^^^ File "/usr/lib/calibre/calibre/customize/conversion.py", line 242, in __call__ ret = self.convert(stream, options, file_ext, log, accelerators) File "/usr/lib/calibre/calibre/ebooks/conversion/plugins/epub_input.py", line 299, in convert raise DRMError(os.path.basename(path)) calibre.ebooks.DRMError: book.epub Two separate things go wrong here. First, process_encryption raises NameError, which its own bare "except:" catches and prints, after which the method returns False. Second, the caller treats that False as "the file is encrypted": epub_input.py:297-299 if os.path.exists(encfile): if not self.process_encryption(encfile, opf, log): raise DRMError(os.path.basename(path)) So the user-visible symptom is a DRM-free file being reported as DRM-protected, which is misleading beyond the conversion failure itself. Expected result --------------- The file converts, with the obfuscated fonts decrypted, as it did before the security update. Root cause ---------- Upstream calibre wires the guard up as follows: - src/calibre/ebooks/conversion/plugins/epub_input.py imports it locally inside process_encryption: from calibre.utils.filenames import is_existing_subpath - src/calibre/utils/filenames.py defines is_existing_subpath(child, parent) - that function calls is_path_inside(parent, child), also defined in src/calibre/utils/filenames.py In 8.5.0+ds-1+deb13u3, only the call site is present: $ grep -rn --include='*.py' "is_existing_subpath" /usr/lib/calibre/calibre/ /usr/lib/calibre/calibre/ebooks/conversion/plugins/epub_input.py:79: if (tkey and is_existing_subpath(path, container_base)): $ grep -rn --include='*.py' "def is_existing_subpath(\|def is_path_inside(" \ /usr/lib/calibre/calibre/ (no output) The import is absent as well, both at module level and inside process_encryption, which is why this surfaces as NameError rather than ImportError. Three pieces are therefore missing: the import statement, is_existing_subpath, and is_path_inside. Security impact --------------- As far as I can tell, none: the package fails closed. The NameError is raised before decrypt_font() is reached, and the enclosing bare "except:" turns the whole call into "return False", so the vulnerable write path described in CVE-2026-25636 cannot execute at all. The mitigation is thus effective, but at the price of breaking conversion of every font-obfuscated EPUB. Suggested fix ------------- Add the two helper functions to calibre/utils/filenames.py and the local import to process_encryption, matching upstream. Other suites ------------ The same CVE fix was backported to bullseye (5.12.0+dfsg-1+deb11u5) and bookworm (6.13.0+repack-2+deb12u9). I have not checked whether those packages carry the same omission; it seems worth verifying. Unstable ships calibre 9.12.0+ds+~0.10.6-1, which contains the complete upstream fix (released upstream in 9.2.0) and is not affected. -- System Information Debian Release: 13.6 (trixie) Architecture: amd64 Observed in a Docker container based on the official python:3.14-slim image, with calibre installed from trixie main via apt. No calibre plugins are installed and no configuration was changed; the failure is reproducible on a freshly built image. Versions of packages calibre depends on: ii calibre 8.5.0+ds-1+deb13u3 ii python3 3.13.5-1

