Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-PyMuPDF for
openSUSE:Leap:16.0 checked in at 2026-06-02 10:49:33
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:16.0/python-PyMuPDF (Old)
and /work/SRC/openSUSE:Leap:16.0/.python-PyMuPDF.new.1937 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-PyMuPDF"
Tue Jun 2 10:49:33 2026 rev:5 rq: version:1.21.1
Changes:
--------
--- /work/SRC/openSUSE:Leap:16.0/python-PyMuPDF/python-PyMuPDF.changes
2025-07-15 17:56:06.993050107 +0200
+++
/work/SRC/openSUSE:Leap:16.0/.python-PyMuPDF.new.1937/python-PyMuPDF.changes
2026-06-02 10:49:34.387889020 +0200
@@ -1,0 +2,6 @@
+Fri Mar 20 15:03:12 UTC 2026 - Markéta Machová <[email protected]>
+
+- CVE-2026-3029: path traversal and arbitrary file write via the
+ `embedded_get` function in `_main_.py` (bsc#1259921)
+
+-------------------------------------------------------------------
New:
----
CVE-2026-3029.patch
----------(New B)----------
New: WARN: CVE-2026-3029.patch not found in changes
----------(New E)----------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-PyMuPDF.spec ++++++
--- /var/tmp/diff_new_pack.WA5sVk/_old 2026-06-02 10:49:35.043916228 +0200
+++ /var/tmp/diff_new_pack.WA5sVk/_new 2026-06-02 10:49:35.047916393 +0200
@@ -28,6 +28,8 @@
Group: Development/Libraries/Python
URL: https://github.com/pymupdf/PyMuPDF
Source:
https://files.pythonhosted.org/packages/source/P/PyMuPDF/PyMuPDF-%{version}.tar.gz
+# PATCH-FIX-UPSTREAM CVE-2026-3029.patch bsc#1259921
+Patch0: CVE-2026-3029.patch
BuildRequires: %{python_module devel}
BuildRequires: %{python_module pip}
BuildRequires: %{python_module setuptools}
++++++ CVE-2026-3029.patch ++++++
>From 603cafe38a183b8bab34f16d05043b4185d8d40a Mon Sep 17 00:00:00 2001
From: Julian Smith <[email protected]>
Date: Fri, 21 Nov 2025 14:23:45 +0000
Subject: [PATCH] Make `pymupdf embed-extract` safe by default.
Fixes #4767.
---
changes.txt | 3 ++
docs/module.rst | 3 +-
src/__main__.py | 9 +++++
tests/test_4767.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+), 1 deletion(-)
create mode 100644 tests/test_4767.py
Index: PyMuPDF-1.21.1/fitz/__main__.py
===================================================================
--- PyMuPDF-1.21.1.orig/fitz/__main__.py
+++ PyMuPDF-1.21.1/fitz/__main__.py
@@ -355,6 +355,12 @@ def embedded_get(args):
except ValueError:
sys.exit("no such embedded file '%s'" % args.name)
filename = args.output if args.output else d["filename"]
+ if not args.unsafe and not args.output:
+ if os.path.exists(filename):
+ sys.exit(f'refusing to overwrite existing file with stored name:
{filename}')
+ filename_abs = os.path.abspath(filename)
+ if not filename_abs.startswith(os.getcwd() + os.sep):
+ sys.exit(f'refusing to write stored name outside current
directory: {filename}')
output = open(filename, "wb")
output.write(stream)
output.close()
@@ -1028,6 +1034,9 @@ def main():
ps_embed_extract.add_argument("input", type=str, help="PDF filename")
ps_embed_extract.add_argument("-name", required=True, help="name of entry")
ps_embed_extract.add_argument("-password", help="password")
+ ps_embed_extract.add_argument("-unsafe", default=False,
action="store_true",
+ help="allow write to stored name even if an existing file or outside
current directory"
+ )
ps_embed_extract.add_argument(
"-output", help="output filename, default is stored name"
)
Index: PyMuPDF-1.21.1/tests/test_4767.py
===================================================================
--- /dev/null
+++ PyMuPDF-1.21.1/tests/test_4767.py
@@ -0,0 +1,86 @@
+import shutil
+import os
+import pymupdf
+import subprocess
+import sys
+
+
+def test_4767():
+ '''
+ Check handling of unsafe paths in `pymupdf embed-extract`.
+ '''
+ with pymupdf.open() as document:
+ document.new_page()
+ document.embfile_add(
+ 'evil_entry',
+ b'poc:traversal test\n',
+ filename="../../test.txt",
+ ufilename="../../test.txt",
+ desc="poc",
+ )
+ document.embfile_add(
+ 'evil_entry2',
+ b'poc:traversal test\n',
+ filename="test2.txt",
+ ufilename="test2.txt",
+ desc="poc",
+ )
+ path = os.path.abspath(f'{__file__}/../../tests/test_4767.pdf')
+ document.save(path)
+ testdir =
os.path.abspath(f'{__file__}/../../tests/test_4767_dir').replace('\\', '/')
+ shutil.rmtree(testdir, ignore_errors=1)
+ os.makedirs(f'{testdir}/one/two', exist_ok=1)
+
+ def run(command, *, check=0, capture=1):
+ print(f'Running: {command}')
+ cp = subprocess.run(
+ command, shell=1,
+ text=1,
+ check=check,
+ stdout=subprocess.PIPE if capture else None,
+ stderr=subprocess.STDOUT if capture else None,
+ )
+ print(cp.stdout)
+ return cp
+
+ def get_paths():
+ paths = list()
+ for dirpath, dirnames, filenames in os.walk(testdir):
+ for filename in filenames:
+ path = f'{dirpath}/{filename}'.replace('\\', '/')
+ paths.append(path)
+ return paths
+
+ cp = run(f'cd {testdir}/one/two && {sys.executable} -m pymupdf
embed-extract {path} -name evil_entry')
+ print(cp.stdout)
+ assert cp.returncode
+ assert cp.stdout == 'refusing to write stored name outside current
directory: ../../test.txt\n'
+ assert not get_paths()
+
+ cp = run(f'cd {testdir}/one/two && {sys.executable} -m pymupdf
embed-extract {path} -name evil_entry -unsafe')
+ assert cp.returncode == 0
+ assert cp.stdout == "saved entry 'evil_entry' as '../../test.txt'\n"
+ paths = get_paths()
+ print(f'{paths=}')
+ assert paths == [f'{testdir}/test.txt']
+
+ cp = run(f'cd {testdir}/one/two && {sys.executable} -m pymupdf
embed-extract {path} -name evil_entry2')
+ assert not cp.returncode
+ assert cp.stdout == "saved entry 'evil_entry2' as 'test2.txt'\n"
+ paths = get_paths()
+ print(f'{paths=}')
+ assert paths == [f'{testdir}/test.txt', f'{testdir}/one/two/test2.txt']
+
+ cp = run(f'cd {testdir}/one/two && {sys.executable} -m pymupdf
embed-extract {path} -name evil_entry2')
+ assert cp.returncode
+ assert cp.stdout == "refusing to overwrite existing file with stored name:
test2.txt\n"
+ paths = get_paths()
+ print(f'{paths=}')
+ assert paths == [f'{testdir}/test.txt', f'{testdir}/one/two/test2.txt']
+
+ cp = run(f'cd {testdir}/one/two && {sys.executable} -m pymupdf
embed-extract {path} -name evil_entry2 -unsafe')
+ assert not cp.returncode
+ assert cp.stdout == "saved entry 'evil_entry2' as 'test2.txt'\n"
+ paths = get_paths()
+ print(f'{paths=}')
+ assert paths == [f'{testdir}/test.txt', f'{testdir}/one/two/test2.txt']
++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.WA5sVk/_old 2026-06-02 10:49:35.095918384 +0200
+++ /var/tmp/diff_new_pack.WA5sVk/_new 2026-06-02 10:49:35.099918550 +0200
@@ -1,7 +1,7 @@
-mtime: 1751814458
-commit: 44eb43121027c38f40f8098cccf6248b7a4b459d74a52ec44d3ccbec26295389
+mtime: 1774019064
+commit: 5e2d23574c29b17095035609e6bc5837a20e967046f289bda5a9c6c58a3fdccb
url: https://src.opensuse.org/pool/python-PyMuPDF
-revision: 44eb43121027c38f40f8098cccf6248b7a4b459d74a52ec44d3ccbec26295389
+revision: 5e2d23574c29b17095035609e6bc5837a20e967046f289bda5a9c6c58a3fdccb
trackingbranch: Leap-16.0
projectscmsync: https://src.opensuse.org/openSUSE/Leap
++++++ build.specials.obscpio ++++++
++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore 1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore 2026-03-20 16:04:24.000000000 +0100
@@ -0,0 +1 @@
+.osc