Security Advisory — Path Traversal (CWE-22)
Severity: MEDIUM (CVSS 5.3 — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)
CWE: CWE-22 — Improper Limitation of a Pathname to a Restricted Directory
Affected file: ebooklib/utils.py, lines 128–130
Reporter: Conner Webber (conner.webber000@gmail.com)
90-day disclosure deadline: 2026-06-06
Summary
Directory.read() in ebooklib/utils.py joins a base directory path with a subname value derived from epub OPF manifest href attributes without sanitizing for path traversal sequences:
open(os.path.join(self.directory_path, subname), "rb")
The href values from the manifest are URL-decoded via unquote (lines 1563–1607), meaning an attacker can use %2e%2e%2f (URL-encoded ../) in manifest hrefs to escape the intended directory and read arbitrary files from the filesystem.
Additionally, file_name values from the manifest are retained on EpubItem objects without sanitization, creating a zip-slip risk in any downstream code that uses these filenames for writing.
Impact
- Arbitrary file read — A crafted epub can read files outside the epub directory when processed by ebooklib
- Zip-slip risk — Unsanitized
file_name on EpubItem objects can cause path traversal when consuming applications write these files
- Affects any application that processes untrusted epub files with ebooklib (e-readers, converters, validators, etc.)
Steps to Reproduce
- Create an epub with a manifest entry containing a traversal path:
<item id="evil" href="%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd" media-type="text/plain"/>
- Process the epub with ebooklib —
Directory.read() will resolve and open /etc/passwd (or equivalent)
Suggested Fix
Sanitize subname in Directory.read() to reject paths containing .. components:
import os
def read(self, subname):
# Prevent path traversal
safe_path = os.path.normpath(subname)
if safe_path.startswith('..') or os.path.isabs(safe_path):
raise ValueError(f"Path traversal detected in: {subname}")
full_path = os.path.join(self.directory_path, safe_path)
# Verify resolved path is within directory_path
if not os.path.realpath(full_path).startswith(os.path.realpath(self.directory_path)):
raise ValueError(f"Path traversal detected in: {subname}")
with open(full_path, "rb") as f:
return f.read()
Also sanitize file_name from manifest hrefs before storing on EpubItem objects — strip directory components or reject traversal sequences.
Note
Private vulnerability reporting (PVRA) is not enabled on this repository, so this is filed as a public issue. I recommend enabling PVRA at Settings → Code security → Private vulnerability reporting for future security disclosures.
Security Advisory — Path Traversal (CWE-22)
Severity: MEDIUM (CVSS 5.3 — AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)
CWE: CWE-22 — Improper Limitation of a Pathname to a Restricted Directory
Affected file:
ebooklib/utils.py, lines 128–130Reporter: Conner Webber (conner.webber000@gmail.com)
90-day disclosure deadline: 2026-06-06
Summary
Directory.read()inebooklib/utils.pyjoins a base directory path with asubnamevalue derived from epub OPF manifesthrefattributes without sanitizing for path traversal sequences:The
hrefvalues from the manifest are URL-decoded viaunquote(lines 1563–1607), meaning an attacker can use%2e%2e%2f(URL-encoded../) in manifest hrefs to escape the intended directory and read arbitrary files from the filesystem.Additionally,
file_namevalues from the manifest are retained onEpubItemobjects without sanitization, creating a zip-slip risk in any downstream code that uses these filenames for writing.Impact
file_nameonEpubItemobjects can cause path traversal when consuming applications write these filesSteps to Reproduce
Directory.read()will resolve and open/etc/passwd(or equivalent)Suggested Fix
Sanitize
subnameinDirectory.read()to reject paths containing..components:Also sanitize
file_namefrom manifest hrefs before storing onEpubItemobjects — strip directory components or reject traversal sequences.Note
Private vulnerability reporting (PVRA) is not enabled on this repository, so this is filed as a public issue. I recommend enabling PVRA at Settings → Code security → Private vulnerability reporting for future security disclosures.