CVE-2026-73248 exposes a security boundary failure in calibre's template system that you need to understand even if you believe you've already secured it. The vulnerability stems from how the allow_python_templates=False flag interacts with nested template resolution through the template() function.
Here is what actually happens: calibre provides a Python-based template system for formatting e-book metadata, and administrators can disable it by setting allow_python_templates=False. This flag was intended to prevent arbitrary Python execution when processing untrusted e-book files. However, the template() function—which resolves nested template calls within composite templates—does not inherit or propagate this security boundary down its call chain. When a composite template invokes template() to resolve a nested call, the inner resolution runs without checking whether Python templates are allowed at that deeper level. An attacker who crafts a malicious EPUB or OPF file can embed a template that uses the composite_template path to smuggle Python code through this gap.
The critical failure is not a missing check; it is the absence of security context propagation between nested evaluation contexts. The protection model assumes that every entry point will enforce the flag, but the template() function was never written to participate in that contract. It resolves templates as a feature, not as a security boundary.
What this means for your deployment: simply setting allow_python_templates=False is insufficient. You must treat all metadata from untrusted sources as potentially hostile, regardless of configuration flags, because the interaction surface between template resolution functions can undermine those flags. If you process EPUB, OPF, or PDF files from external sources, consider whether the template evaluation feature is necessary at all for your workflow — and if it is, isolate it in a sandboxed environment rather than relying on configuration flags to bound its behavior. The existence of allow_python_templates=False likely created false confidence that Python execution was bounded, when in practice it was only bounded at specific entry points, not throughout the evaluation chain.