CVE-2026-25635: From Help File to Hacked — Calibre CHM Path Traversal to RCE

0x5t
0x5t avatar
Security Researcher
Team: RaptX
Posts: --
Joined: 2024
Posted:  |  Tags: RCE, Path Traversal, Calibre, CHM  |  CVSS 8.6 HIGH
CVE-2026-25635: Calibre CHM Path Traversal to RCE — attack chain diagram
TL;DR: A path traversal vulnerability in Calibre 9.1.0's CHM reader allows a malicious help file to write arbitrary files anywhere the user has write permissions. On Windows, this achieves code execution by dropping a payload into the Startup folder, which runs automatically on the next login.

Vulnerability Chain: Path Traversal → Arbitrary File Write → Code Execution

Introduction

Compiled HTML Help (CHM) files are Microsoft's legacy help file format. Despite being decades old, they remain widely used — and widely converted. Calibre, the most popular ebook management application with millions of users, supports CHM as an input format, converting it to EPUB, MOBI, PDF, and other formats.

While auditing Calibre's format parsers, I found a path traversal vulnerability in the CHM reader that allows a malicious help file to write arbitrary files to the victim's system. On Windows, this is a direct path to code execution.

This is a separate finding from the EPUB path traversal vulnerability I disclosed previously. Both affect Calibre 9.1.0, but target different parsing components with different exploitation strategies.

The Discovery

CHM files are essentially archives containing HTML pages, images, and other resources. When Calibre converts a CHM file, it extracts these resources to a temporary directory before processing them. The extraction logic lives in src/calibre/ebooks/chm/reader.py.

The vulnerability is straightforward: Calibre strips only the leading slash from internal CHM paths, but never sanitizes .. directory traversal sequences. An attacker can craft a CHM file with internal paths that escape the extraction directory and write to arbitrary locations on disk.

Technical Deep Dive

The First Bug: Insufficient Sanitization (Line 351)

When building the list of files inside the CHM archive, Calibre runs:

paths.append(path.lstrip('/'))

This strips the leading / from each path — but that's it. Path components like .. pass through completely untouched.

The Second Bug: Uncontained File Write (Lines 184-198)

During extraction, each path from the CHM is joined directly with the output directory and written to disk:

for path in self.Contents():
    fpath = path                              # ATTACKER CONTROLLED
    lpath = os.path.join(output_dir, fpath)   # PATH TRAVERSAL
    self._ensure_dir(lpath)                   # Creates dirs OUTSIDE output_dir
    data = self.GetFile(path)
    # ...
    with open(lpath, 'wb') as f:
        f.write(data)                         # ARBITRARY FILE WRITE

The critical issues:

  1. fpath is taken directly from the CHM archive without sanitization
  2. os.path.join(output_dir, fpath) with .. sequences escapes the extraction directory
  3. _ensure_dir() helpfully creates any intermediate directories needed along the traversal path
  4. open(lpath, 'wb') writes attacker-controlled data to the escaped path

Unlike the EPUB vulnerability (which corrupts existing files via XOR), this CHM bug gives full arbitrary file write — the attacker controls both the path and the entire file content.

Exploitation: Arbitrary File Write to RCE on Windows

Target: The Windows Startup Folder

On Windows, any executable or script placed in the user's Startup folder runs automatically on login:

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\

The challenge is reaching this path from the temporary extraction directory using .. traversal. The Calibre temp directory sits several levels deep, so we need enough ..\ components to escape up to the %APPDATA% root.

The 8.3 Short Name Trick

The "Start Menu" directory contains a space, which can cause issues in path handling. Windows NTFS supports 8.3 short filenames — an alias system from the DOS era. The short name for "Start Menu" is STARTM~1. Using this short name avoids any space-related parsing issues:

/..\\..\\..\\..\\Roaming\\Microsoft\\Windows\\STARTM~1\\Programs\\Startup\\rce.bat

After lstrip('/') removes the leading slash, and os.path.join() resolves the .. sequences, this path escapes the temp directory and lands directly in the Startup folder.

The Payload

The CHM file embeds a batch script as the file content:

@echo off
calc.exe

This is a benign proof-of-concept payload. A real attacker could drop a reverse shell, ransomware, or any other executable.

The Attack in Action

Step 1: Attacker Creates Malicious CHM

The attacker generates a CHM file containing the traversal path and payload. The file looks and behaves like a normal help file — Calibre doesn't validate internal paths before extraction.

Step 2: Victim Converts the CHM

The victim imports the CHM into Calibre and converts it to another format (GUI: "Convert books" or CLI: ebook-convert):

$ ebook-convert poc.chm output.epub

Step 3: Payload Drops to Startup

During conversion, Calibre extracts the CHM contents. The traversal path escapes the temp directory and rce.bat is written to the Startup folder:

> dir "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"
rce.bat    78 bytes

Step 4: Code Execution on Next Login

On the next Windows login (or reboot), rce.bat executes automatically. In the PoC, calc.exe launches — confirming arbitrary code execution.

Proof of Concept

The video above demonstrates the full attack chain: crafting the malicious CHM, converting it in Calibre, and calc.exe launching on the next login.

Impact Analysis

Why This Is Worse Than the EPUB Bug

Factor EPUB Vulnerability CHM Vulnerability
Write primitive XOR corruption of first 1040 bytes Full arbitrary file write (any content, any size)
Prerequisite UUID brute-force (~minutes) None — direct exploitation
Target constraint File must exist with predictable content No constraints — creates new files
RCE path Shell init script corruption (Linux) Startup folder drop (Windows)

Direct Impacts

  1. Arbitrary File Write: Attacker writes any file anywhere the user has permissions
  2. Code Execution: Via Windows Startup folder, cron jobs, shell profiles, or any auto-executed path
  3. Persistence: The dropped payload survives reboots and runs on every login
  4. Stealth: The conversion appears to work normally — no errors or warnings

Platform Testing

Platform Interface Status
Windows GUI (Convert books) Vulnerable
Windows CLI (ebook-convert) Vulnerable
Linux CLI (ebook-convert) Vulnerable

Root Cause Analysis

  1. Insufficient Sanitization: lstrip('/') only removes leading slashes — .. sequences are preserved entirely
  2. No Path Containment: Calibre never verifies that resolved paths stay within the extraction directory
  3. Helpful Directory Creation: _ensure_dir() creates directories along the traversal path, ensuring the write succeeds
  4. Trust in Untrusted Data: Internal CHM paths are treated as safe without validation

Timeline

Date Event
2025-02-01 Vulnerability discovered
2025-02-01 RCE escalation confirmed on Windows
2026-02-06 Vendor patch release
2026-02-06 Public disclosure

Conclusion

This vulnerability is a textbook case of path traversal leading to code execution. Unlike the EPUB vulnerability that required cryptographic brute-forcing to weaponize a limited XOR corruption primitive, the CHM bug provides unrestricted arbitrary file write — making exploitation trivial. No brute-forcing, no constraints on content, no requirement that the target file already exists.

On Windows, the Startup folder provides a clean and reliable path to code execution. On Linux, the same traversal could target ~/.bashrc, cron directories, or SSH authorized keys. The vulnerability affects both the GUI and CLI on all platforms.

Given that CHM files are commonly shared and converted, and that Calibre is the de facto standard for ebook management, users should update immediately.

References