已关闭
fix(cve): 修复 CVE-2026-6357 在 python-pip 中的漏洞 #275
infra_team创建于 6月12日关闭于 23 天前
fix(cve): 修复 CVE-2026-6357 在 python-pip 中的漏洞 #275
已关闭
共 3 个文件变更+272-1
| @@ -0,0 +1,267 @@ | |||
| 1 | +From b369bfc96cc524e00c267e1693290e6599c36bad Mon Sep 17 00:00:00 2001 | ||
| 2 | +From: Damian Shaw <damian.peter.shaw@gmail.com> | ||
| 3 | +Date: Fri, 17 Apr 2026 09:52:38 -0400 | ||
| 4 | +Subject: [PATCH] fix CVE-2026-6357 - Split the pip self-version check to get info before run | ||
| 5 | + | ||
| 6 | +fix CVE-2026-6357 - Split the pip self-version check to get info before run | ||
| 7 | + | ||
| 8 | +Upstream-commit: https://github.com/pypa/pip/commit/b369bfc96cc524e00c267e1693290e6599c36bad | ||
| 9 | +Signed-off-by: infra_team <zhaiwenjie1@huawei.com> | ||
| 10 | +--- | ||
| 11 | +--- pip-23.3.1-original/src/pip/_internal/cli/base_command.py 2023-10-21 19:06:38.000000000 +0800 | ||
| 12 | ++++ pip-23.3.1/src/pip/_internal/cli/base_command.py 2026-06-12 07:33:15.000000000 +0800 | ||
| 13 | +@@ -1,5 +1,6 @@ | ||
| 14 | + """Base Command class, and related routines""" | ||
| 15 | + | ||
| 16 | ++import contextlib | ||
| 17 | + import functools | ||
| 18 | + import logging | ||
| 19 | + import logging.config | ||
| 20 | +@@ -7,6 +8,7 @@ | ||
| 21 | + import os | ||
| 22 | + import sys | ||
| 23 | + import traceback | ||
| 24 | ++from collections.abc import Iterator | ||
| 25 | + from optparse import Values | ||
| 26 | + from typing import Any, Callable, List, Optional, Tuple | ||
| 27 | + | ||
| 28 | +@@ -79,7 +81,8 @@ | ||
| 29 | + def add_options(self) -> None: | ||
| 30 | + pass | ||
| 31 | + | ||
| 32 | +- def handle_pip_version_check(self, options: Values) -> None: | ||
| 33 | ++ @contextlib.contextmanager | ||
| 34 | ++ def pip_version_check(self, options: Values) -> Iterator[None]: | ||
| 35 | + """ | ||
| 36 | + This is a no-op so that commands by default do not do the pip version | ||
| 37 | + check. | ||
| 38 | +@@ -87,6 +90,7 @@ | ||
| 39 | + # Make sure we do the pip version check if the index_group options | ||
| 40 | + # are present. | ||
| 41 | + assert not hasattr(options, "no_index") | ||
| 42 | ++ yield | ||
| 43 | + | ||
| 44 | + def run(self, options: Values, args: List[str]) -> int: | ||
| 45 | + raise NotImplementedError | ||
| 46 | +@@ -225,12 +229,10 @@ | ||
| 47 | + | ||
| 48 | + return exc_logging_wrapper | ||
| 49 | + | ||
| 50 | +- try: | ||
| 51 | +- if not options.debug_mode: | ||
| 52 | +- run = intercepts_unhandled_exc(self.run) | ||
| 53 | +- else: | ||
| 54 | +- run = self.run | ||
| 55 | +- rich_traceback.install(show_locals=True) | ||
| 56 | ++ if not options.debug_mode: | ||
| 57 | ++ run = intercepts_unhandled_exc(self.run) | ||
| 58 | ++ else: | ||
| 59 | ++ run = self.run | ||
| 60 | ++ rich_traceback.install(show_locals=True) | ||
| 61 | ++ with self.pip_version_check(options): | ||
| 62 | + return run(options, args) | ||
| 63 | +- finally: | ||
| 64 | +- self.handle_pip_version_check(options) | ||
| 65 | +--- pip-23.3.1-original/src/pip/_internal/cli/req_command.py 2023-10-21 19:06:38.000000000 +0800 | ||
| 66 | ++++ pip-23.3.1/src/pip/_internal/cli/req_command.py 2026-06-12 07:32:41.000000000 +0800 | ||
| 67 | +@@ -5,9 +5,11 @@ | ||
| 68 | + PackageFinder machinery and all its vendored dependencies, etc. | ||
| 69 | + """ | ||
| 70 | + | ||
| 71 | ++import contextlib | ||
| 72 | + import logging | ||
| 73 | + import os | ||
| 74 | + import sys | ||
| 75 | ++from collections.abc import Iterator | ||
| 76 | + from functools import partial | ||
| 77 | + from optparse import Values | ||
| 78 | + from typing import TYPE_CHECKING, Any, List, Optional, Tuple | ||
| 79 | +@@ -33,7 +35,10 @@ | ||
| 80 | + from pip._internal.req.req_file import parse_requirements | ||
| 81 | + from pip._internal.req.req_install import InstallRequirement | ||
| 82 | + from pip._internal.resolution.base import BaseResolver | ||
| 83 | +-from pip._internal.self_outdated_check import pip_self_version_check | ||
| 84 | ++from pip._internal.self_outdated_check import ( | ||
| 85 | ++ pip_self_version_check_fetch, | ||
| 86 | ++ pip_self_version_check_emit, | ||
| 87 | ++) | ||
| 88 | + from pip._internal.utils.temp_dir import ( | ||
| 89 | + TempDirectory, | ||
| 90 | + TempDirectoryTypeRegistry, | ||
| 91 | +@@ -161,7 +166,8 @@ | ||
| 92 | + This also corresponds to the commands that permit the pip version check. | ||
| 93 | + """ | ||
| 94 | + | ||
| 95 | +- def handle_pip_version_check(self, options: Values) -> None: | ||
| 96 | ++ @contextlib.contextmanager | ||
| 97 | ++ def pip_version_check(self, options: Values) -> Iterator[None]: | ||
| 98 | + """ | ||
| 99 | + Do the pip version check if not disabled. | ||
| 100 | + | ||
| 101 | +@@ -171,21 +177,39 @@ | ||
| 102 | + assert hasattr(options, "no_index") | ||
| 103 | + | ||
| 104 | + if options.disable_pip_version_check or options.no_index: | ||
| 105 | ++ yield | ||
| 106 | + return | ||
| 107 | + | ||
| 108 | +- # Otherwise, check if we're using the latest version of pip available. | ||
| 109 | +- session = self._build_session( | ||
| 110 | +- options, | ||
| 111 | +- retries=0, | ||
| 112 | +- timeout=min(5, options.timeout), | ||
| 113 | +- # This is set to ensure the function does not fail when truststore is | ||
| 114 | +- # specified in use-feature but cannot be loaded. This usually raises a | ||
| 115 | +- # CommandError and shows a nice user-facing error, but this function is not | ||
| 116 | +- # called in that try-except block. | ||
| 117 | +- fallback_to_certifi=True, | ||
| 118 | +- ) | ||
| 119 | +- with session: | ||
| 120 | +- pip_self_version_check(session, options) | ||
| 121 | ++ remote_version_str: Optional[str] = None | ||
| 122 | ++ try: | ||
| 123 | ++ session = self._build_session( | ||
| 124 | ++ options, | ||
| 125 | ++ retries=0, | ||
| 126 | ++ timeout=min(5, options.timeout), | ||
| 127 | ++ # This is set to ensure the function does not fail when truststore is | ||
| 128 | ++ # specified in use-feature but cannot be loaded. This usually raises a | ||
| 129 | ++ # CommandError and shows a nice user-facing error, but this function is not | ||
| 130 | ++ # called in that try-except block. | ||
| 131 | ++ fallback_to_certifi=True, | ||
| 132 | ++ ) | ||
| 133 | ++ with session: | ||
| 134 | ++ remote_version_str = pip_self_version_check_fetch(session, options) | ||
| 135 | ++ except Exception: | ||
| 136 | ++ logger.warning("There was an error checking the latest version of pip.") | ||
| 137 | ++ logger.debug("See below for error", exc_info=True) | ||
| 138 | ++ | ||
| 139 | ++ if remote_version_str is None: | ||
| 140 | ++ yield | ||
| 141 | ++ return | ||
| 142 | ++ | ||
| 143 | ++ try: | ||
| 144 | ++ yield | ||
| 145 | ++ finally: | ||
| 146 | ++ try: | ||
| 147 | ++ pip_self_version_check_emit(remote_version_str) | ||
| 148 | ++ except Exception: | ||
| 149 | ++ logger.warning("There was an error checking the latest version of pip.") | ||
| 150 | ++ logger.debug("See below for error", exc_info=True) | ||
| 151 | + | ||
| 152 | + | ||
| 153 | + KEEPABLE_TEMPDIR_TYPES = [ | ||
| 154 | +--- pip-23.3.1-original/src/pip/_internal/self_outdated_check.py 2023-10-21 19:06:38.000000000 +0800 | ||
| 155 | ++++ pip-23.3.1/src/pip/_internal/self_outdated_check.py 2026-06-12 07:32:18.000000000 +0800 | ||
| 156 | +@@ -1,5 +1,4 @@ | ||
| 157 | + import datetime | ||
| 158 | +-import functools | ||
| 159 | + import hashlib | ||
| 160 | + import json | ||
| 161 | + import logging | ||
| 162 | +@@ -187,21 +186,9 @@ | ||
| 163 | + return str(best_candidate.version) | ||
| 164 | + | ||
| 165 | + | ||
| 166 | +-def _self_version_check_logic( | ||
| 167 | +- *, | ||
| 168 | +- state: SelfCheckState, | ||
| 169 | +- current_time: datetime.datetime, | ||
| 170 | +- local_version: DistributionVersion, | ||
| 171 | +- get_remote_version: Callable[[], Optional[str]], | ||
| 172 | ++def _compute_upgrade_prompt( | ||
| 173 | ++ local_version: DistributionVersion, remote_version_str: str | ||
| 174 | + ) -> Optional[UpgradePrompt]: | ||
| 175 | +- remote_version_str = state.get(current_time) | ||
| 176 | +- if remote_version_str is None: | ||
| 177 | +- remote_version_str = get_remote_version() | ||
| 178 | +- if remote_version_str is None: | ||
| 179 | +- logger.debug("No remote pip version found") | ||
| 180 | +- return None | ||
| 181 | +- state.set(remote_version_str, current_time) | ||
| 182 | +- | ||
| 183 | + remote_version = parse_version(remote_version_str) | ||
| 184 | + logger.debug("Remote version of pip: %s", remote_version) | ||
| 185 | + logger.debug("Local version of pip: %s", local_version) | ||
| 186 | +@@ -221,6 +208,62 @@ | ||
| 187 | + return None | ||
| 188 | + | ||
| 189 | + | ||
| 190 | ++def _self_version_check_logic( | ||
| 191 | ++ *, | ||
| 192 | ++ state: SelfCheckState, | ||
| 193 | ++ current_time: datetime.datetime, | ||
| 194 | ++ local_version: DistributionVersion, | ||
| 195 | ++ get_remote_version: Callable[[], Optional[str]], | ||
| 196 | ++) -> Optional[UpgradePrompt]: | ||
| 197 | ++ remote_version_str = state.get(current_time) | ||
| 198 | ++ if remote_version_str is None: | ||
| 199 | ++ remote_version_str = get_remote_version() | ||
| 200 | ++ if remote_version_str is None: | ||
| 201 | ++ logger.debug("No remote pip version found") | ||
| 202 | ++ return None | ||
| 203 | ++ state.set(remote_version_str, current_time) | ||
| 204 | ++ return _compute_upgrade_prompt(local_version, remote_version_str) | ||
| 205 | ++ | ||
| 206 | ++ | ||
| 207 | ++def pip_self_version_check_fetch( | ||
| 208 | ++ session: PipSession, options: optparse.Values | ||
| 209 | ++) -> Optional[str]: | ||
| 210 | ++ """Return the latest pip version from the index, or None. | ||
| 211 | ++ | ||
| 212 | ++ Pair with :func:`pip_self_version_check_emit`. | ||
| 213 | ++ """ | ||
| 214 | ++ installed_dist = get_default_environment().get_distribution("pip") | ||
| 215 | ++ if not installed_dist: | ||
| 216 | ++ return None | ||
| 217 | ++ | ||
| 218 | ++ state = SelfCheckState(cache_dir=options.cache_dir) | ||
| 219 | ++ current_time = datetime.datetime.now(datetime.timezone.utc) | ||
| 220 | ++ remote_version_str = state.get(current_time) | ||
| 221 | ++ if remote_version_str is not None: | ||
| 222 | ++ return remote_version_str | ||
| 223 | ++ | ||
| 224 | ++ remote_version_str = _get_current_remote_pip_version(session, options) | ||
| 225 | ++ if remote_version_str is None: | ||
| 226 | ++ logger.debug("No remote pip version found") | ||
| 227 | ++ return None | ||
| 228 | ++ state.set(remote_version_str, current_time) | ||
| 229 | ++ return remote_version_str | ||
| 230 | ++ | ||
| 231 | ++ | ||
| 232 | ++def pip_self_version_check_emit(remote_version_str: Optional[str]) -> None: | ||
| 233 | ++ """Emit the upgrade prompt if the installed pip is older than the remote.""" | ||
| 234 | ++ if remote_version_str is None: | ||
| 235 | ++ return | ||
| 236 | ++ | ||
| 237 | ++ installed_dist = get_default_environment().get_distribution("pip") | ||
| 238 | ++ if not installed_dist: | ||
| 239 | ++ return | ||
| 240 | ++ | ||
| 241 | ++ upgrade_prompt = _compute_upgrade_prompt(installed_dist.version, remote_version_str) | ||
| 242 | ++ if upgrade_prompt is not None: | ||
| 243 | ++ logger.warning("%s", upgrade_prompt, extra={"rich": True}) | ||
| 244 | ++ | ||
| 245 | ++ | ||
| 246 | + def pip_self_version_check(session: PipSession, options: optparse.Values) -> None: | ||
| 247 | + """Check for an update for pip. | ||
| 248 | + | ||
| 249 | +@@ -233,13 +276,13 @@ | ||
| 250 | + return | ||
| 251 | + | ||
| 252 | + try: | ||
| 253 | ++ state = SelfCheckState(cache_dir=options.cache_dir) | ||
| 254 | ++ current_time = datetime.datetime.now(datetime.timezone.utc) | ||
| 255 | + upgrade_prompt = _self_version_check_logic( | ||
| 256 | +- state=SelfCheckState(cache_dir=options.cache_dir), | ||
| 257 | +- current_time=datetime.datetime.now(datetime.timezone.utc), | ||
| 258 | ++ state=state, | ||
| 259 | ++ current_time=current_time, | ||
| 260 | + local_version=installed_dist.version, | ||
| 261 | +- get_remote_version=functools.partial( | ||
| 262 | +- _get_current_remote_pip_version, session, options | ||
| 263 | +- ), | ||
| 264 | ++ get_remote_version=lambda: _get_current_remote_pip_version(session, options), | ||
| 265 | + ) | ||
| 266 | + if upgrade_prompt is not None: | ||
| 267 | + logger.warning("%s", upgrade_prompt, extra={"rich": True}) | ||
| @@ -6,7 +6,7 @@ pip is the package installer for Python. You can use pip to install packages fro | |||
| 6 | %global bashcompdir %(b=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null); echo ${b:-%{_sysconfdir}/bash_completion.d}) | 6 | %global bashcompdir %(b=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null); echo ${b:-%{_sysconfdir}/bash_completion.d}) |
| 7 | Name: python-%{srcname} | 7 | Name: python-%{srcname} |
| 8 | Version: 23.3.1 | 8 | Version: 23.3.1 |
| 9 | -Release: 13 | 9 | +Release: 14 |
| 10 | Summary: A tool for installing and managing Python packages | 10 | Summary: A tool for installing and managing Python packages |
| 11 | License: MIT and Python and ASL 2.0 and BSD and ISC and LGPLv2 and MPLv2.0 and (ASL 2.0 or BSD) | 11 | License: MIT and Python and ASL 2.0 and BSD and ISC and LGPLv2 and MPLv2.0 and (ASL 2.0 or BSD) |
| 12 | URL: http://www.pip-installer.org | 12 | URL: http://www.pip-installer.org |
| @@ -27,6 +27,7 @@ Patch6009: backport-CVE-2026-25645.patch | |||
| 27 | Patch6010: backport-CVE-2026-3219.patch | 27 | Patch6010: backport-CVE-2026-3219.patch |
| 28 | Patch6011: backport-CVE-2026-44431.patch | 28 | Patch6011: backport-CVE-2026-44431.patch |
| 29 | Patch6012: backport-CVE-2026-8643.patch | 29 | Patch6012: backport-CVE-2026-8643.patch |
| 30 | +Patch6013: backport-CVE-2026-6357.patch | ||
| 30 | 31 | ||
| 31 | Source10: pip-allow-older-versions.patch | 32 | Source10: pip-allow-older-versions.patch |
| 32 | 33 | ||
| @@ -144,6 +145,9 @@ install -D -m0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/pip.conf | |||
| 144 | %{python_wheeldir}/%{python_wheelname} | 145 | %{python_wheeldir}/%{python_wheelname} |
| 145 | 146 | ||
| 146 | %changelog | 147 | %changelog |
| 148 | +* Fri Jun 12 2026 infra_team <zhaiwenjie1@huawei.com> - 23.3.1-14 | ||
| 149 | +- fix CVE-2026-6357 | ||
| 150 | + | ||
| 147 | * Thu Jun 04 2026 fly_fzc <2385803914@qq.com> - 23.3.1-13 | 151 | * Thu Jun 04 2026 fly_fzc <2385803914@qq.com> - 23.3.1-13 |
| 148 | - fix CVE-2026-8643 | 152 | - fix CVE-2026-8643 |
| 149 | 153 | ||