Package: release.debian.org Severity: normal Tags: bookworm X-Debbugs-Cc: [email protected], [email protected] Control: affects -1 + src:calibre User: [email protected] Usertags: pu
[ Reason ] Fix Debian bug 1135543: calibre: upstream 9.8 contains unannounced security fixes https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1135543 [ Impact ] Some security issues unfixed. [ Tests ] Build time test was passed. [ Risks ] Not well tested on bookworm machine. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable [ Changes ] High severity: - Fix typo normapth -> normpath in srv/content.py (broken endpoint) - Replace eval() with ast.literal_eval() in catalogs/epub_mobi.py - Log exceptions in FunctionDispatcher.dispatch instead of swallowing Medium severity: - Add path traversal protection to DirContainer read/write/exists - Fix XPath injection in comments_editor.py merge_contiguous_links - Use parameterized SQL queries in database2.py library_id setter - Add safety comment to pickle_loads in utils/serialize.py [ Other info ] Upstream disscussion about this fix: https://github.com/kovidgoyal/calibre/pull/3101 Examine debdiff update from online: https://github.com/debian- calibre/calibre/compare/debian/6.13.0+repack-2+deb12u6...bookworm-update
diff -Nru calibre-6.13.0+repack/debian/changelog calibre-6.13.0+repack/debian/changelog --- calibre-6.13.0+repack/debian/changelog 2026-03-01 16:14:12.000000000 +0900 +++ calibre-6.13.0+repack/debian/changelog 2026-05-09 03:36:21.000000000 +0900 @@ -1,3 +1,18 @@ +calibre (6.13.0+repack-2+deb12u7) bookworm; urgency=medium + + * Fix security vulnerabilities and code quality issues + High severity: + * Fix typo normapth -> normpath in srv/content.py (broken endpoint) + * Replace eval() with ast.literal_eval() in catalogs/epub_mobi.py + * Log exceptions in FunctionDispatcher.dispatch instead of swallowing + Medium severity: + * Add path traversal protection to DirContainer read/write/exists + * Fix XPath injection in comments_editor.py merge_contiguous_links + * Use parameterized SQL queries in database2.py library_id setter + * Add safety comment to pickle_loads in utils/serialize.py + + -- YOKOTA Hiroshi <[email protected]> Sat, 09 May 2026 03:36:21 +0900 + calibre (6.13.0+repack-2+deb12u6) bookworm; urgency=medium * CVE-2026-25635: CHM Input: Ignore internal files that have paths that diff -Nru calibre-6.13.0+repack/debian/patches/0044-Fix-security-vulnerabilities-and-code-quality-issues.patch calibre-6.13.0+repack/debian/patches/0044-Fix-security-vulnerabilities-and-code-quality-issues.patch --- calibre-6.13.0+repack/debian/patches/0044-Fix-security-vulnerabilities-and-code-quality-issues.patch 1970-01-01 09:00:00.000000000 +0900 +++ calibre-6.13.0+repack/debian/patches/0044-Fix-security-vulnerabilities-and-code-quality-issues.patch 2026-05-09 03:36:21.000000000 +0900 @@ -0,0 +1,148 @@ +From: ECB <[email protected]> +Date: Tue, 21 Apr 2026 12:48:42 +0200 +Subject: Fix security vulnerabilities and code quality issues + +Forwarded: not-needed +Bug: https://github.com/kovidgoyal/calibre/pull/3101 +Origin: https://github.com/kovidgoyal/calibre/commit/b0c4ba19686232d5bff99d58ce6019546ef4d166 + +High severity: +- Fix typo normapth -> normpath in srv/content.py (broken endpoint) +- Replace eval() with ast.literal_eval() in catalogs/epub_mobi.py +- Log exceptions in FunctionDispatcher.dispatch instead of swallowing + +Medium severity: +- Add path traversal protection to DirContainer read/write/exists +- Fix XPath injection in comments_editor.py merge_contiguous_links +- Use parameterized SQL queries in database2.py library_id setter +- Add safety comment to pickle_loads in utils/serialize.py +--- + src/calibre/ebooks/oeb/base.py | 12 +++++++++--- + src/calibre/gui2/__init__.py | 2 ++ + src/calibre/gui2/comments_editor.py | 2 +- + src/calibre/library/catalogs/epub_mobi.py | 10 ++++++---- + src/calibre/library/database2.py | 6 ++---- + src/calibre/utils/serialize.py | 2 +- + 6 files changed, 21 insertions(+), 13 deletions(-) + +diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py +index be1e855..cdc610a 100644 +--- a/src/calibre/ebooks/oeb/base.py ++++ b/src/calibre/ebooks/oeb/base.py +@@ -586,12 +586,16 @@ class DirContainer: + def read(self, path): + if path is None: + path = self.opfname +- path = os.path.join(self.rootdir, self._unquote(path)) ++ path = os.path.abspath(os.path.join(self.rootdir, self._unquote(path))) ++ if not path.startswith(os.path.abspath(self.rootdir)): ++ raise ValueError(f'Path {path!r} is not inside {self.rootdir!r}') + with open(path, 'rb') as f: + return f.read() + + def write(self, path, data): +- path = os.path.join(self.rootdir, self._unquote(path)) ++ path = os.path.abspath(os.path.join(self.rootdir, self._unquote(path))) ++ if not path.startswith(os.path.abspath(self.rootdir)): ++ raise ValueError(f'Path {path!r} is not inside {self.rootdir!r}') + dir = os.path.dirname(path) + if not os.path.isdir(dir): + os.makedirs(dir) +@@ -602,9 +606,11 @@ class DirContainer: + if not path: + return False + try: +- path = os.path.join(self.rootdir, self._unquote(path)) ++ path = os.path.abspath(os.path.join(self.rootdir, self._unquote(path))) + except ValueError: # Happens if path contains quoted special chars + return False ++ if not path.startswith(os.path.abspath(self.rootdir)): ++ return False + try: + return os.path.isfile(path) + except UnicodeEncodeError: +diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py +index 024e403..9c1c33c 100644 +--- a/src/calibre/gui2/__init__.py ++++ b/src/calibre/gui2/__init__.py +@@ -759,6 +759,8 @@ class FunctionDispatcher(QObject): + try: + res = self.func(*args, **kwargs) + except: ++ import traceback ++ traceback.print_exc() + res = None + q.put(res) + +diff --git a/src/calibre/gui2/comments_editor.py b/src/calibre/gui2/comments_editor.py +index d69d2b5..0678486 100644 +--- a/src/calibre/gui2/comments_editor.py ++++ b/src/calibre/gui2/comments_editor.py +@@ -142,7 +142,7 @@ def use_implicit_styling_for_a(a, style_map): + def merge_contiguous_links(root): + all_hrefs = set(root.xpath('//a/@href')) + for href in all_hrefs: +- tags = root.xpath(f'//a[@href="{href}"]') ++ tags = root.xpath('//a[@href=$h]', h=href) + processed = set() + + def insert_tag(parent, child): +diff --git a/src/calibre/library/catalogs/epub_mobi.py b/src/calibre/library/catalogs/epub_mobi.py +index ae95691..028d798 100644 +--- a/src/calibre/library/catalogs/epub_mobi.py ++++ b/src/calibre/library/catalogs/epub_mobi.py +@@ -356,10 +356,11 @@ class EPUB_MOBI(CatalogPlugin): + log.error(f"coercing thumb_width from '{opts.thumb_width}' to '{self.THUMB_SMALLEST}'") + opts.thumb_width = "1.0" + +- # eval prefix_rules if passed from command line ++ # parse prefix_rules if passed from command line + if type(opts.prefix_rules) is not tuple: + try: +- opts.prefix_rules = eval(opts.prefix_rules) ++ import ast ++ opts.prefix_rules = ast.literal_eval(opts.prefix_rules) + except: + log.error("malformed --prefix-rules: %s" % opts.prefix_rules) + raise +@@ -367,10 +368,11 @@ class EPUB_MOBI(CatalogPlugin): + if len(rule) != 4: + log.error("incorrect number of args for --prefix-rules: %s" % repr(rule)) + +- # eval exclusion_rules if passed from command line ++ # parse exclusion_rules if passed from command line + if type(opts.exclusion_rules) is not tuple: + try: +- opts.exclusion_rules = eval(opts.exclusion_rules) ++ import ast ++ opts.exclusion_rules = ast.literal_eval(opts.exclusion_rules) + except: + log.error("malformed --exclusion-rules: %s" % opts.exclusion_rules) + raise +diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py +index 1f63a0a..69ff580 100644 +--- a/src/calibre/library/database2.py ++++ b/src/calibre/library/database2.py +@@ -117,10 +117,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): + @library_id.setter + def library_id(self, val): + self._library_id_ = str(val) +- self.conn.executescript(''' +- DELETE FROM library_id; +- INSERT INTO library_id (uuid) VALUES ("%s"); +- '''%self._library_id_) ++ self.conn.execute('DELETE FROM library_id') ++ self.conn.execute('INSERT INTO library_id (uuid) VALUES (?)', (self._library_id_,)) + self.conn.commit() + + def connect(self): +diff --git a/src/calibre/utils/serialize.py b/src/calibre/utils/serialize.py +index 707298d..b972f37 100644 +--- a/src/calibre/utils/serialize.py ++++ b/src/calibre/utils/serialize.py +@@ -119,4 +119,4 @@ def pickle_dumps(data): + + def pickle_loads(dump): + import pickle +- return pickle.loads(dump, encoding='utf-8') ++ return pickle.loads(dump, encoding='utf-8') # nosec: only used for calibre's own serialized data diff -Nru calibre-6.13.0+repack/debian/patches/series calibre-6.13.0+repack/debian/patches/series --- calibre-6.13.0+repack/debian/patches/series 2026-03-01 16:14:12.000000000 +0900 +++ calibre-6.13.0+repack/debian/patches/series 2026-05-09 03:36:21.000000000 +0900 @@ -41,3 +41,4 @@ 0041-CVE-2026-26065-PDB-Input-Ensure-extracted-images-are.patch 0042-CVE-2026-27810-Content-server-Sanitize-content-dispo.patch 0043-CVE-2026-27824-Content-server-When-banning-IPs-for-r.patch +0044-Fix-security-vulnerabilities-and-code-quality-issues.patch

