Skip to content

Commit bdd9eb6

Browse files
authored
feat(python): add GitHub provenance verification for prebuilt binaries (#8820)
## Problem Precompiled Python binaries from `astral-sh/python-build-standalone` lack provenance verification. Unlike Ruby (which already supports GitHub Artifact Attestations), Python installs have no mechanism to verify that downloaded binaries were actually produced by the expected CI workflow in the expected repository. Additionally, there is no downgrade protection: if a lockfile records that provenance was previously verified, nothing prevents an attacker from stripping that metadata and serving unverified binaries. ## Solution Add GitHub Artifact Attestations support for precompiled Python binaries, following the same pattern already established for Ruby: 1. **New setting**: `python.github_attestations` (env: `MISE_PYTHON_GITHUB_ATTESTATIONS`) overrides the global `github_attestations` setting specifically for Python. Defaults to the global value (which is `true`). 2. **Lockfile provenance recording**: `mise lock` now records `provenance = "github-attestations"` in Python platform entries when the setting is enabled. 3. **Install-time verification**: `mise install` verifies downloaded tarballs against GitHub Artifact Attestations using the sigstore verification crate, with owner/repo hardcoded to `astral-sh/python-build-standalone`. 4. **Downgrade protection**: If the lockfile records provenance but verification is disabled at install time, the install fails with a "downgrade attack" error, preventing provenance stripping attacks. ## Test plan - [x] `mise run test:e2e test_lockfile_python` — all tests pass - [x] Tests verify: provenance recorded when enabled, not recorded when disabled, downgrade attack detected when lockfile has provenance but verification is off - [x] `mise run build` and `mise run lint` pass 🤖 Generated with the assistance of OpenCode (claude-opus-4.6).
1 parent 0fafcaf commit bdd9eb6

19 files changed

+259
-11
lines changed

docs/dev-tools/mise-lock.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ mise use node@24
194194
Backend support for lockfile features varies:
195195

196196
-**Full support** (version + checksum + size + URL): `aqua`, `http`, `github`, `gitlab`
197-
- _Provenance support_: `aqua`, `github`, `core:ruby` (precompiled binaries), `core:zig` (install-time)
197+
- _Provenance support_: `aqua`, `github`, `core:python` (precompiled binaries), `core:ruby` (precompiled binaries), `core:zig` (install-time)
198198
- ⚠️ **Partial support** (version + URL + provenance): `vfox` (tool plugins only)
199199
- ⚠️ **Partial support** (version + checksum + size): `ubi`
200200
- 📝 **Basic support** (version + checksum): `core` (some tools)

e2e-win/python.Tests.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11

22
Describe 'python' {
3+
BeforeAll {
4+
$env:MISE_PYTHON_GITHUB_ATTESTATIONS = "0"
5+
}
6+
37
It 'executes python 3.12.0' {
48
mise x python@3.12.0 -- where python
59
mise x python@3.12.0 -- python --version | Should -Be "Python 3.12.0"

e2e-win/uv.Tests.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11

22
Describe 'uv' {
3+
BeforeAll {
4+
$env:MISE_PYTHON_GITHUB_ATTESTATIONS = "0"
5+
}
6+
37
BeforeEach {
48
$originalPath = Get-Location
59
Set-Location TestDrive:

e2e/backend/test_pipx_deep_dependencies_slow

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ assert_fail "pipx"
2121

2222
# Use only precompiled python
2323
export MISE_PYTHON_COMPILE=0
24+
export MISE_PYTHON_GITHUB_ATTESTATIONS=0
2425

2526
# Set up a 3-step installation: python@3.12.3 > pipx@1.5.0 > pipx:mkdocs@1.6.0
2627
cat >.mise.toml <<EOF

e2e/backend/test_pipx_postinstall_hook

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ assert_fail "pipx"
2020

2121
# Use precompiled python and uvx (the default)
2222
export MISE_PYTHON_COMPILE=0
23+
export MISE_PYTHON_GITHUB_ATTESTATIONS=0
2324
export MISE_PIPX_UVX=1
2425

2526
# Set up mise-managed Python with a pipx package that has a postinstall hook

e2e/backend/test_pipx_uvx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ assert_fail "pipx"
1515

1616
# Use precompiled python
1717
export MISE_PYTHON_COMPILE=0
18+
export MISE_PYTHON_GITHUB_ATTESTATIONS=0
1819
export MISE_PIPX_UVX=1
1920

2021
# Set up a 2-step installation: pipx@1.5.0 > pipx:mkdocs@1.6.0

e2e/backend/test_pipx_venv_symlink

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ assert_fail "pipx"
1515

1616
# Use precompiled python and disable uvx to use pipx (which uses mise's Python)
1717
export MISE_PYTHON_COMPILE=0
18+
export MISE_PYTHON_GITHUB_ATTESTATIONS=0
1819
export MISE_PIPX_UVX=0
1920

2021
# Set up mise-managed Python and pipx
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
# Test GitHub artifact attestations verification for Python precompiled binaries
3+
# Depends on GitHub Releases and Attestations APIs; may fail due to rate limits or outages.
4+
5+
export MISE_PYTHON_COMPILE=0
6+
export MISE_PYTHON_GITHUB_ATTESTATIONS=1
7+
8+
# Use a recent Python version that has attestations in python-build-standalone.
9+
# Older releases (e.g. 3.12.3) predate GitHub attestation support and will fail.
10+
output=$(mise install python@3.13.5 2>&1) || true
11+
echo "$output"
12+
13+
# Verify attestation verification was attempted and succeeded
14+
assert_contains "echo \"$output\"" "verify GitHub artifact attestations"
15+
assert_contains "echo \"$output\"" "✓ GitHub artifact attestations verified"
16+
17+
# Verify the installed Python works
18+
assert "mise x python@3.13.5 -- python --version" "Python 3.13.5"

e2e/core/test_python_precompiled

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env bash
22

33
export MISE_PYTHON_COMPILE=0
4+
export MISE_PYTHON_GITHUB_ATTESTATIONS=0
45
assert_contains "mise use python@3.12.3 2>&1" "cpython-"
56
assert_contains "mise x -- python --version" "Python 3.12.3"
67

e2e/core/test_python_uv_venv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
set -euo pipefail
44

55
export MISE_EXPERIMENTAL=1
6+
export MISE_PYTHON_GITHUB_ATTESTATIONS=0
67

78
# Test uv is used for manually defined venv
89
cat >mise.toml <<EOF

0 commit comments

Comments
 (0)