Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python39 for openSUSE:Factory 
checked in at 2024-10-25 19:19:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python39 (Old)
 and      /work/SRC/openSUSE:Factory/.python39.new.2020 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python39"

Fri Oct 25 19:19:37 2024 rev:67 rq:1218097 version:3.9.20

Changes:
--------
--- /work/SRC/openSUSE:Factory/python39/python39.changes        2024-09-29 
18:10:50.474134779 +0200
+++ /work/SRC/openSUSE:Factory/.python39.new.2020/python39.changes      
2024-10-25 19:20:29.680759399 +0200
@@ -1,0 +2,13 @@
+Thu Oct 24 16:09:00 UTC 2024 - Matej Cepl <[email protected]>
+
+- Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
+  path names provided when creating a virtual environment
+  (bsc#1232241, CVE-2024-9287)
+
+-------------------------------------------------------------------
+Wed Oct  2 16:18:29 UTC 2024 - Matej Cepl <[email protected]>
+
+- Drop .pyc files from docdir for reproducible builds
+  (bsc#1230906).
+
+-------------------------------------------------------------------

New:
----
  CVE-2024-9287-venv_path_unquoted.patch

BETA DEBUG BEGIN:
  New:
- Add CVE-2024-9287-venv_path_unquoted.patch to properly quote
  path names provided when creating a virtual environment
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python39.spec ++++++
--- /var/tmp/diff_new_pack.hA1Fcq/_old  2024-10-25 19:20:33.388914114 +0200
+++ /var/tmp/diff_new_pack.hA1Fcq/_new  2024-10-25 19:20:33.392914281 +0200
@@ -194,6 +194,9 @@
 # PATCH-FIX-UPSTREAM sphinx-802.patch [email protected]
 # status_iterator method moved between the Sphinx versions
 Patch51:        sphinx-802.patch
+# PATCH-FIX-UPSTREAM CVE-2024-9287-venv_path_unquoted.patch 
gh#python/cpython#124651 [email protected]
+# venv should properly quote path names provided when creating a venv
+Patch52:        CVE-2024-9287-venv_path_unquoted.patch
 
 BuildRequires:  autoconf-archive
 BuildRequires:  automake
@@ -467,6 +470,7 @@
 %patch -P 48 -p1
 %patch -P 50 -p1
 %patch -P 51 -p1
+%patch -P 52 -p1
 
 # drop Autoconf version requirement
 sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
@@ -801,6 +805,11 @@
 echo %{sitedir}/_import_failed > 
%{buildroot}/%{sitedir}/site-packages/zzzz-import-failed-hooks.pth
 %endif
 
+# For the purposes of reproducibility, it is necessary to eliminate any *.pyc 
files inside documentation dirs
+if [ -d %{buildroot}%{_defaultdocdir} ] ; then
+find %{buildroot}%{_defaultdocdir} -type f -name \*.pyc -ls -exec rm -vf '{}' 
\;
+fi
+
 %if %{with general}
 %files -n %{python_pkg_name}-tk
 %{sitedir}/tkinter

++++++ CVE-2024-9287-venv_path_unquoted.patch ++++++
>From b6a3bbd155c558cdcda482629073e492437db3d0 Mon Sep 17 00:00:00 2001
From: y5c4l3 <[email protected]>
Date: Sat, 28 Sep 2024 02:09:07 +0800
Subject: [PATCH] Quote template strings in `venv` activation scripts

This patch properly quotes template strings in `venv` activation
scripts. This mitigates potential command injection.

Signed-off-by: y5c4l3 <[email protected]>
---
 Lib/test/test_venv.py                                                   |   81 
++++++++++
 Lib/venv/__init__.py                                                    |   42 
++++-
 Lib/venv/scripts/common/activate                                        |    6 
 Lib/venv/scripts/nt/activate.bat                                        |    6 
 Lib/venv/scripts/posix/activate.csh                                     |    6 
 Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst |    1 
 6 files changed, 128 insertions(+), 14 deletions(-)
 create mode 100644 
Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst

--- a/Lib/test/test_venv.py
+++ b/Lib/test/test_venv.py
@@ -9,6 +9,7 @@ import ensurepip
 import os
 import os.path
 import re
+import shlex
 import shutil
 import struct
 import subprocess
@@ -85,6 +86,10 @@ class BaseTest(unittest.TestCase):
             result = f.read()
         return result
 
+    def assertEndsWith(self, string, tail):
+        if not string.endswith(tail):
+            self.fail(f"String {string!r} does not end with {tail!r}")
+
 class BasicTest(BaseTest):
     """Test venv module functionality."""
 
@@ -342,6 +347,82 @@ class BasicTest(BaseTest):
             'import sys; print(sys.executable)'])
         self.assertEqual(out.strip(), envpy.encode())
 
+    # gh-124651: test quoted strings
+    @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
+    def test_special_chars_bash(self):
+        """
+        Test that the template strings are quoted properly (bash)
+        """
+        rmtree(self.env_dir)
+        bash = shutil.which('bash')
+        if bash is None:
+            self.skipTest('bash required for this test')
+        env_name = '"\';&&$e|\'"'
+        env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+        builder = venv.EnvBuilder(clear=True)
+        builder.create(env_dir)
+        activate = os.path.join(env_dir, self.bindir, 'activate')
+        test_script = os.path.join(self.env_dir, 'test_special_chars.sh')
+        with open(test_script, "w") as f:
+            f.write(f'source {shlex.quote(activate)}\n'
+                    'python -c \'import sys; print(sys.executable)\'\n'
+                    'python -c \'import os; 
print(os.environ["VIRTUAL_ENV"])\'\n'
+                    'deactivate\n')
+        out, err = check_output([bash, test_script])
+        lines = out.splitlines()
+        self.assertTrue(env_name.encode() in lines[0])
+        self.assertEndsWith(lines[1], env_name.encode())
+
+    # gh-124651: test quoted strings
+    @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
+    def test_special_chars_csh(self):
+        """
+        Test that the template strings are quoted properly (csh)
+        """
+        rmtree(self.env_dir)
+        csh = shutil.which('tcsh') or shutil.which('csh')
+        if csh is None:
+            self.skipTest('csh required for this test')
+        env_name = '"\';&&$e|\'"'
+        env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+        builder = venv.EnvBuilder(clear=True)
+        builder.create(env_dir)
+        activate = os.path.join(env_dir, self.bindir, 'activate.csh')
+        test_script = os.path.join(self.env_dir, 'test_special_chars.csh')
+        with open(test_script, "w") as f:
+            f.write(f'source {shlex.quote(activate)}\n'
+                    'python -c \'import sys; print(sys.executable)\'\n'
+                    'python -c \'import os; 
print(os.environ["VIRTUAL_ENV"])\'\n'
+                    'deactivate\n')
+        out, err = check_output([csh, test_script])
+        lines = out.splitlines()
+        self.assertTrue(env_name.encode() in lines[0])
+        self.assertEndsWith(lines[1], env_name.encode())
+
+    # gh-124651: test quoted strings on Windows
+    @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
+    def test_special_chars_windows(self):
+        """
+        Test that the template strings are quoted properly on Windows
+        """
+        rmtree(self.env_dir)
+        env_name = "'&&^$e"
+        env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+        builder = venv.EnvBuilder(clear=True)
+        builder.create(env_dir)
+        activate = os.path.join(env_dir, self.bindir, 'activate.bat')
+        test_batch = os.path.join(self.env_dir, 'test_special_chars.bat')
+        with open(test_batch, "w") as f:
+            f.write('@echo off\n'
+                    f'"{activate}" & '
+                    f'{self.exe} -c "import sys; print(sys.executable)" & '
+                    f'{self.exe} -c "import os; 
print(os.environ[\'VIRTUAL_ENV\'])" & '
+                    'deactivate')
+        out, err = check_output([test_batch])
+        lines = out.splitlines()
+        self.assertTrue(env_name.encode() in lines[0])
+        self.assertEndsWith(lines[1], env_name.encode())
+
     @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
     def test_unicode_in_batch_file(self):
         """
--- a/Lib/venv/__init__.py
+++ b/Lib/venv/__init__.py
@@ -11,6 +11,7 @@ import subprocess
 import sys
 import sysconfig
 import types
+import shlex
 
 
 CORE_VENV_DEPS = ('pip', 'setuptools')
@@ -348,11 +349,41 @@ class EnvBuilder:
         :param context: The information for the environment creation request
                         being processed.
         """
-        text = text.replace('__VENV_DIR__', context.env_dir)
-        text = text.replace('__VENV_NAME__', context.env_name)
-        text = text.replace('__VENV_PROMPT__', context.prompt)
-        text = text.replace('__VENV_BIN_NAME__', context.bin_name)
-        text = text.replace('__VENV_PYTHON__', context.env_exe)
+        replacements = {
+            '__VENV_DIR__': context.env_dir,
+            '__VENV_NAME__': context.env_name,
+            '__VENV_PROMPT__': context.prompt,
+            '__VENV_BIN_NAME__': context.bin_name,
+            '__VENV_PYTHON__': context.env_exe,
+        }
+
+        def quote_ps1(s):
+            """
+            This should satisfy PowerShell quoting rules [1], unless the quoted
+            string is passed directly to Windows native commands [2].
+            [1]: 
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules
+            [2]: 
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing#passing-arguments-that-contain-quote-characters
+            """
+            s = s.replace("'", "''")
+            return f"'{s}'"
+
+        def quote_bat(s):
+            return s
+
+        # gh-124651: need to quote the template strings properly
+        quote = shlex.quote
+        script_path = context.script_path
+        if script_path.endswith('.ps1'):
+            quote = quote_ps1
+        elif script_path.endswith('.bat'):
+            quote = quote_bat
+        else:
+            # fallbacks to POSIX shell compliant quote
+            quote = shlex.quote
+
+        replacements = {key: quote(s) for key, s in replacements.items()}
+        for key, quoted in replacements.items():
+            text = text.replace(key, quoted)
         return text
 
     def install_scripts(self, context, path):
@@ -393,6 +424,7 @@ class EnvBuilder:
                     data = f.read()
                 if not srcfile.endswith(('.exe', '.pdb')):
                     try:
+                        context.script_path = srcfile
                         data = data.decode('utf-8')
                         data = self.replace_variables(data, context)
                         data = data.encode('utf-8')
--- a/Lib/venv/scripts/common/activate
+++ b/Lib/venv/scripts/common/activate
@@ -37,11 +37,11 @@ deactivate () {
 # unset irrelevant variables
 deactivate nondestructive
 
-VIRTUAL_ENV="__VENV_DIR__"
+VIRTUAL_ENV=__VENV_DIR__
 export VIRTUAL_ENV
 
 _OLD_VIRTUAL_PATH="$PATH"
-PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+PATH="$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
 export PATH
 
 # unset PYTHONHOME if set
@@ -54,7 +54,7 @@ fi
 
 if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
     _OLD_VIRTUAL_PS1="${PS1:-}"
-    PS1="__VENV_PROMPT__${PS1:-}"
+    PS1=__VENV_PROMPT__"${PS1:-}"
     export PS1
 fi
 
--- a/Lib/venv/scripts/nt/activate.bat
+++ b/Lib/venv/scripts/nt/activate.bat
@@ -8,7 +8,7 @@ if defined _OLD_CODEPAGE (
     "%SystemRoot%\System32\chcp.com" 65001 > nul
 )
 
-set VIRTUAL_ENV=__VENV_DIR__
+set "VIRTUAL_ENV=__VENV_DIR__"
 
 if not defined PROMPT set PROMPT=$P$G
 
@@ -16,7 +16,7 @@ if defined _OLD_VIRTUAL_PROMPT set PROMP
 if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%
 
 set _OLD_VIRTUAL_PROMPT=%PROMPT%
-set PROMPT=__VENV_PROMPT__%PROMPT%
+set "PROMPT=__VENV_PROMPT__%PROMPT%"
 
 if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%
 set PYTHONHOME=
@@ -24,7 +24,7 @@ set PYTHONHOME=
 if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
 if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
 
-set PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%
+set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%"
 
 :END
 if defined _OLD_CODEPAGE (
--- a/Lib/venv/scripts/posix/activate.csh
+++ b/Lib/venv/scripts/posix/activate.csh
@@ -8,16 +8,16 @@ alias deactivate 'test $?_OLD_VIRTUAL_PA
 # Unset irrelevant variables.
 deactivate nondestructive
 
-setenv VIRTUAL_ENV "__VENV_DIR__"
+setenv VIRTUAL_ENV __VENV_DIR__
 
 set _OLD_VIRTUAL_PATH="$PATH"
-setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+setenv PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
 
 
 set _OLD_VIRTUAL_PROMPT="$prompt"
 
 if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
-    set prompt = "__VENV_PROMPT__$prompt"
+    set prompt = __VENV_PROMPT__"$prompt"
 endif
 
 alias pydoc python -m pydoc
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
@@ -0,0 +1 @@
+Properly quote template strings in :mod:`venv` activation scripts.

Reply via email to