From 987cc51cd4506b794cefa893046b0cd09361f8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Nowacki?= Date: Wed, 21 Oct 2026 18:06:11 +0200 Subject: [PATCH] Require b2sdk 2.13.2, certifi 2026.10.19, pip 26.2.2, and uv 0.13.4 or newer to address the eMudhra / emSign CA certificate incident --- .github/workflows/cd.yml | 4 ++- .github/workflows/ci.yml | 4 ++- .readthedocs.yml | 6 ++++ changelog.d/+emsign-certificates.fixed.md | 1 + docker/Dockerfile.template | 18 +++++++++-- noxfile.py | 2 +- pyproject.toml | 9 ++++-- uv.lock | 37 +++++++++++++++-------- 8 files changed, 60 insertions(+), 21 deletions(-) create mode 100644 changelog.d/+emsign-certificates.fixed.md diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 20485cc5b..6bf83461b 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -8,7 +8,7 @@ env: CD: "true" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PYTHON_DEFAULT_VERSION: "3.12" - UV_VERSION: "0.8.24" + UV_VERSION: "0.13.4" jobs: deploy: @@ -204,6 +204,8 @@ jobs: uses: docker/build-push-action@v3 with: context: . + pull: true + no-cache: true push: true tags: ${{ steps.docker_tags_prep.outputs.docker_tags }} platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48db8dfed..e77d0e707 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ on: env: PYTHON_DEFAULT_VERSION: "3.12" - UV_VERSION: "0.8.24" + UV_VERSION: "0.13.4" jobs: lint: @@ -185,6 +185,8 @@ jobs: uses: docker/build-push-action@v5 with: context: . + pull: true + no-cache: true load: true tags: backblazeit/b2:test platforms: linux/amd64 diff --git a/.readthedocs.yml b/.readthedocs.yml index a588ba217..0551f989f 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,6 +8,12 @@ build: os: ubuntu-24.04 tools: python: "3.14" + apt_packages: + - ca-certificates + jobs: + pre_create_environment: + - python -m pip install --upgrade 'pip @ https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl#sha256=fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70' + - python -m pip install --upgrade 'uv==0.13.4' sphinx: configuration: doc/source/conf.py diff --git a/changelog.d/+emsign-certificates.fixed.md b/changelog.d/+emsign-certificates.fixed.md new file mode 100644 index 000000000..f7783947e --- /dev/null +++ b/changelog.d/+emsign-certificates.fixed.md @@ -0,0 +1 @@ +Require b2sdk 2.13.2, certifi 2026.10.19, pip 26.2.2, and uv 0.13.4 or newer to address the eMudhra / emSign CA certificate incident. Update CI and container builds to use the patched tools and refresh container system certificates. diff --git a/docker/Dockerfile.template b/docker/Dockerfile.template index 5baed5e42..a5fc0b0a6 100644 --- a/docker/Dockerfile.template +++ b/docker/Dockerfile.template @@ -1,6 +1,18 @@ -FROM python:${python_version}-slim as builder +FROM python:${python_version}-slim AS base -RUN apt-get update -y && apt-get install git patchelf -y && pip install -U uv==0.8.24 +RUN apt-get update -y \ + && apt-get install --no-install-recommends -y ca-certificates \ + && rm -rf /var/lib/apt/lists/* +# Bootstrap pip with the checksum published in the Python security advisory. +RUN python -m pip install --no-cache-dir --upgrade \ + 'pip @ https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl#sha256=fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70' + +FROM base AS builder + +RUN apt-get update -y \ + && apt-get install --no-install-recommends -y git patchelf \ + && rm -rf /var/lib/apt/lists/* \ + && python -m pip install --no-cache-dir uv==0.13.4 WORKDIR /b2 COPY ./b2 /b2/b2 @@ -13,7 +25,7 @@ RUN rm -r .venv && mkdir __pypackages__ RUN uv export --locked --no-dev --extra full --no-hashes --no-editable -o requirements.txt RUN uv pip install --compile-bytecode --python /usr/local/bin/python --prefix __pypackages__ -r requirements.txt -FROM python:${python_version}-slim +FROM base LABEL vendor=${vendor} LABEL name="${name}" diff --git a/noxfile.py b/noxfile.py index 0a9626e89..07991a07f 100644 --- a/noxfile.py +++ b/noxfile.py @@ -675,7 +675,7 @@ def build_and_test_docker(session): """ test_image_tag = 'b2:test' generate_dockerfile(session) - session.run('docker', 'build', '-t', test_image_tag, '.', external=True) + session.run('docker', 'build', '--pull', '--no-cache', '-t', test_image_tag, '.', external=True) run_docker_tests(session, test_image_tag) diff --git a/pyproject.toml b/pyproject.toml index 2d414499c..79d875bc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,8 @@ classifiers = [ dependencies = [ "argcomplete>=3.5.2,<4", "arrow>=1.0.2,<2.0.0", - "b2sdk>=2.13.0,<3", + "b2sdk>=2.13.2,<3", + "certifi>=2026.10.19", "docutils>=0.18.1,<0.22", "idna~=3.4; platform_system == 'Java'", "rst2ansi==0.1.5", @@ -38,7 +39,7 @@ full = [ "pydantic>=2.0.1,<3" ] license = [ - "pip>=26.1", + "pip>=26.2.2", "pip-licenses~=5.0", "pipdeptree>=2.9,<3", "prettytable~=3.9", @@ -47,6 +48,7 @@ license = [ [dependency-groups] nox = [ "nox>=2025.11.12", + "pip>=26.2.2", ] doc = [ "sadisplay>=0.4.9", @@ -60,6 +62,7 @@ format = [ "ruff~=0.8.4", ] lint = [ + "pip>=26.2.2", "ruff~=0.8.4", "pytest>=9.0.3,<10", "tenacity>=9.1.4,<10", @@ -70,6 +73,7 @@ release = [ "towncrier==23.11.0", ] test = [ + "pip>=26.2.2", "coverage>=7.13.5,<8", "pexpect>=4.9.0,<5", "pytest>=9.0.3,<10", @@ -89,6 +93,7 @@ bundle = [ ] [tool.uv] +required-version = ">=0.13.4" no-build-isolation-package = ["patchelf-wrapper", "staticx"] [project.urls] diff --git a/uv.lock b/uv.lock index 895da2af5..ad7d6fb80 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 5 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.11'", @@ -85,6 +85,7 @@ dependencies = [ { name = "argcomplete" }, { name = "arrow" }, { name = "b2sdk" }, + { name = "certifi" }, { name = "docutils" }, { name = "idna", marker = "platform_system == 'Java'" }, { name = "platformdirs" }, @@ -126,6 +127,7 @@ format = [ ] lint = [ { name = "liccheck" }, + { name = "pip" }, { name = "pytest" }, { name = "ruff" }, { name = "setuptools" }, @@ -133,6 +135,7 @@ lint = [ ] nox = [ { name = "nox" }, + { name = "pip" }, ] release = [ { name = "towncrier" }, @@ -141,6 +144,7 @@ test = [ { name = "coverage" }, { name = "more-itertools" }, { name = "pexpect" }, + { name = "pip" }, { name = "pytest" }, { name = "pytest-cov" }, { name = "pytest-forked" }, @@ -153,10 +157,11 @@ test = [ requires-dist = [ { name = "argcomplete", specifier = ">=3.5.2,<4" }, { name = "arrow", specifier = ">=1.0.2,<2.0.0" }, - { name = "b2sdk", specifier = ">=2.13.0,<3" }, + { name = "b2sdk", specifier = ">=2.13.2,<3" }, + { name = "certifi", specifier = ">=2026.10.19" }, { name = "docutils", specifier = ">=0.18.1,<0.22" }, { name = "idna", marker = "platform_system == 'Java'", specifier = "~=3.4" }, - { name = "pip", marker = "extra == 'license'", specifier = ">=26.1" }, + { name = "pip", marker = "extra == 'license'", specifier = ">=26.2.2" }, { name = "pip-licenses", marker = "extra == 'license'", specifier = "~=5.0" }, { name = "pipdeptree", marker = "extra == 'license'", specifier = ">=2.9,<3" }, { name = "platformdirs", specifier = ">=3.11.0,<5" }, @@ -187,17 +192,22 @@ doc = [ format = [{ name = "ruff", specifier = "~=0.8.4" }] lint = [ { name = "liccheck", specifier = ">=0.9.2" }, + { name = "pip", specifier = ">=26.2.2" }, { name = "pytest", specifier = ">=9.0.3,<10" }, { name = "ruff", specifier = "~=0.8.4" }, { name = "setuptools", specifier = ">=60,<80" }, { name = "tenacity", specifier = ">=9.1.4,<10" }, ] -nox = [{ name = "nox", specifier = ">=2025.11.12" }] +nox = [ + { name = "nox", specifier = ">=2025.11.12" }, + { name = "pip", specifier = ">=26.2.2" }, +] release = [{ name = "towncrier", specifier = "==23.11.0" }] test = [ { name = "coverage", specifier = ">=7.13.5,<8" }, { name = "more-itertools", specifier = ">=11.0.2,<12" }, { name = "pexpect", specifier = ">=4.9.0,<5" }, + { name = "pip", specifier = ">=26.2.2" }, { name = "pytest", specifier = ">=9.0.3,<10" }, { name = "pytest-cov", specifier = ">=7.1.0,<8" }, { name = "pytest-forked", specifier = ">=1.6.0,<2" }, @@ -208,17 +218,18 @@ test = [ [[package]] name = "b2sdk" -version = "2.13.1" +version = "2.13.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, + { name = "certifi" }, { name = "logfury" }, { name = "requests" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/32/1d/18ad9b5ed6408b74d159a65544a786813149aaf34128e888c6c42ed49595/b2sdk-2.13.1.tar.gz", hash = "sha256:45f91907bb677f916c920e9ccc3d120fdbd2b11d0059ff2cd06360973c281e6f", size = 210410, upload-time = "2026-10-04T16:19:26.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/b6/1a79829948f3fa23b61216cf6330dbc8d1bb0999ae95a7e9c031d08b35ea/b2sdk-2.13.2.tar.gz", hash = "sha256:ff71d70f24694158c0d6eb1b904bf2cff74e61d46e4b34e3d32186189045866a", size = 210426, upload-time = "2026-10-21T15:30:00.835Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/0c/5f3b9a75835f4dd897ee65b3a4d719700e7583989c38a01dba76280ca18e/b2sdk-2.13.1-py3-none-any.whl", hash = "sha256:ce6533be17f75785ce9511f063b9dd1142adbe71fa124417005b65bad69e8abe", size = 301509, upload-time = "2026-10-04T16:19:24.848Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ba/29431ba5a72402d59b6f13cc4ea9ce501174ae60b115289e493005d20335/b2sdk-2.13.2-py3-none-any.whl", hash = "sha256:f2d7663392d869c17d44b7304bae6e06ecefda18742b197a693a93298943310d", size = 301525, upload-time = "2026-10-21T15:29:59.438Z" }, ] [[package]] @@ -232,11 +243,11 @@ wheels = [ [[package]] name = "certifi" -version = "2026.2.25" +version = "2026.10.19" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/1436c50cc46699de0230fbaacc1d1de7bfec413176099949e9d5112e88f2/certifi-2026.10.19.tar.gz", hash = "sha256:035c1e85572b141bf1c3a3eff0e33a8eb74917522f2559075ff8d2fea780a1ae", size = 137598, upload-time = "2026-10-20T02:24:16.604Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, + { url = "https://files.pythonhosted.org/packages/c4/51/29046e48f693c54e5b7412216d447a1d8362c9653148d98c02cdf65fa733/certifi-2026.10.19-py3-none-any.whl", hash = "sha256:42d35340cc5b9ba78e818ddbff0c5b1c2b779de448a340fd1b989f5fa8670e1b", size = 136464, upload-time = "2026-10-20T02:24:15.072Z" }, ] [[package]] @@ -849,11 +860,11 @@ wheels = [ [[package]] name = "pip" -version = "26.1" +version = "26.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/7e/d2b04004e1068ad4fdfa2f227b839b5d03e602e47cdbbf49de71137c9546/pip-26.1.tar.gz", hash = "sha256:81e13ebcca3ffa8cc85e4deff5c27e1ee26dea0aa7fc2f294a073ac208806ff3", size = 1840316, upload-time = "2026-04-26T21:00:05.406Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/e8/0842d757e483e895e670f655084cfe8b8c72580c6769a76b30b2789a0608/pip-26.2.2.tar.gz", hash = "sha256:3a8e5c800492787f33a4114ef54444546c340df428974ebba17e0fd47e11af2f", size = 1863336, upload-time = "2026-10-20T16:36:29.008Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/7a/be4bd8bcbb24ea475856dd68159d78b03b2bb53dae369f69c9606b8888f5/pip-26.1-py3-none-any.whl", hash = "sha256:4e8486d821d814b77319acb7b9e8bf5a4ee7590a643e7cb21029f209be8573c1", size = 1812804, upload-time = "2026-04-26T21:00:03.194Z" }, + { url = "https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl", hash = "sha256:fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70", size = 1819850, upload-time = "2026-10-20T16:36:27.046Z" }, ] [[package]]