diff --git a/meta-python/recipes-devtools/python/python3-virtualenv/CVE-2026-113713.patch b/meta-python/recipes-devtools/python/python3-virtualenv/CVE-2026-113713.patch new file mode 100644 index 0000000000..6fcf11480a --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-virtualenv/CVE-2026-113713.patch @@ -0,0 +1,113 @@ +From b81995c3feab9e1edb453c75ffc6616e1a77335e Mon Sep 17 00:00:00 2001 +From: Bernát Gábor +Date: Sat, 17 Oct 2026 10:09:55 -0700 +Subject: [PATCH] fix(seed): copy from temporary app-data (#3437) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +CVE: CVE-2026-113713 +Upstream-Status: Backport [https://github.com/pypa/virtualenv/commit/b81995c3feab9e1edb453c75ffc6616e1a77335e] + +Backport Changes: +- Omit the upstream release changelog fragment. + +Signed-off-by: Hetvi Thakar +--- + .../seed/embed/via_app_data/via_app_data.py | 4 +- + .../embed/test_bootstrap_link_via_app_data.py | 52 ++++++++++++++++++- + 2 files changed, 53 insertions(+), 3 deletions(-) + +diff --git a/src/virtualenv/seed/embed/via_app_data/via_app_data.py b/src/virtualenv/seed/embed/via_app_data/via_app_data.py +index 092ef74..44ba70d 100644 +--- a/src/virtualenv/seed/embed/via_app_data/via_app_data.py ++++ b/src/virtualenv/seed/embed/via_app_data/via_app_data.py +@@ -37,7 +37,9 @@ LOGGER = logging.getLogger(__name__) + class FromAppData(BaseEmbed): + def __init__(self, options: VirtualEnvOptions) -> None: + super().__init__(options) +- self.symlinks = options.symlink_app_data ++ self.symlinks = options.symlink_app_data and not self.app_data.transient ++ if options.symlink_app_data and self.app_data.transient: ++ LOGGER.debug("copy seed packages because temporary app-data is removed after creation") + + @classmethod + def add_parser_arguments(cls, parser: ArgumentParser, interpreter: PythonInfo, app_data: AppData) -> None: +diff --git a/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py b/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py +index a9917c4..fe07df7 100644 +--- a/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py ++++ b/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py +@@ -3,9 +3,11 @@ from __future__ import annotations + import contextlib + import csv + import hashlib ++import logging + import os + import sys + from base64 import urlsafe_b64encode ++from pathlib import Path + from stat import S_IWGRP, S_IWOTH, S_IWUSR + from subprocess import Popen, check_call, run + from threading import Thread +@@ -21,11 +23,57 @@ from virtualenv.seed.wheels.embed import BUNDLE_FOLDER, BUNDLE_SUPPORT + from virtualenv.util.path import safe_delete + + if TYPE_CHECKING: +- from pathlib import Path +- + from pytest_mock import MockerFixture + + ++@pytest.mark.parametrize( ++ "source", ++ [ ++ pytest.param("environment", id="environment"), ++ pytest.param("configuration", id="configuration"), ++ pytest.param("command-line", id="command-line"), ++ ], ++) ++def test_transient_seed_survives_cache_cleanup(tmp_path: Path, source: str, unusable_cache: Path) -> None: ++ config: Final = tmp_path / "virtualenv.ini" ++ config.write_text("[virtualenv]\nsymlink_app_data = true\n" if source == "configuration" else "", encoding="utf-8") ++ env: Final = { ++ **os.environ, ++ "VIRTUALENV_CONFIG_FILE": str(config), ++ "VIRTUALENV_OVERRIDE_APP_DATA": str(unusable_cache), ++ } ++ if source == "environment": ++ env["VIRTUALENV_SYMLINK_APP_DATA"] = "true" ++ args: Final = [str(tmp_path / "env"), "--no-periodic-update", "--no-setuptools"] ++ if source == "command-line": ++ args.append("--symlink-app-data") ++ session: Final = cli_run(args, env=env) ++ assert ( ++ session.creator.app_data.transient, ++ Path(str(session.creator.app_data)).exists(), ++ (session.creator.purelib / "pip" / "__init__.py").is_file(), ++ ) == (True, False, True) ++ ++ ++def test_transient_seed_reports_copy_fallback( ++ tmp_path: Path, caplog: pytest.LogCaptureFixture, unusable_cache: Path ++) -> None: ++ caplog.set_level(logging.DEBUG) ++ cli_run( ++ [str(tmp_path / "env"), "--no-periodic-update", "--no-setuptools"], ++ env={**os.environ, "VIRTUALENV_OVERRIDE_APP_DATA": str(unusable_cache), "VIRTUALENV_SYMLINK_APP_DATA": "true"}, ++ setup_logging=False, ++ ) ++ assert "copy seed packages because temporary app-data is removed after creation" in caplog.text ++ ++ ++@pytest.fixture ++def unusable_cache(tmp_path: Path) -> Path: ++ blocked: Final = tmp_path / "blocked" ++ blocked.touch() ++ return blocked / "cache" ++ ++ + @pytest.mark.usefixtures("_no_coverage") + @pytest.mark.parametrize( + ("metadata_file", "content"), +-- +2.35.6 diff --git a/meta-python/recipes-devtools/python/python3-virtualenv_21.2.1.bb b/meta-python/recipes-devtools/python/python3-virtualenv_21.2.1.bb index b13b7d4fdd..adeff3939a 100644 --- a/meta-python/recipes-devtools/python/python3-virtualenv_21.2.1.bb +++ b/meta-python/recipes-devtools/python/python3-virtualenv_21.2.1.bb @@ -30,6 +30,7 @@ SRC_URI += " \ file://CVE-2026-113716.patch \ file://CVE-2026-113722_p1.patch \ file://CVE-2026-113722_p2.patch \ + file://CVE-2026-113713.patch \ " BBCLASSEXTEND = "native nativesdk"