v2026.3.18

jdx/misev2026.3.18Mar 31, 2026by mise-en-dev

AI Summary

Adds Python provenance verification via GitHub Artifact Attestations and fixes critical shim recursion bugs.

Key Highlights

  • Python provenance verification using GitHub Artifact Attestations from astral-sh.
  • Shim recursion guards preventing infinite loops in devcontainers and exec templates.
  • Go backend support for deeply nested sub-modules.
  • Registry entry for `svgo` (SVG Optimizer).

New Features

  • Python GitHub Artifact Attestations verification
  • svgo registry entry

Full Release Notes

This release adds supply-chain security improvements for Python, fixes several shim recursion issues that could cause system hangs, and improves Go backend version resolution for deeply nested sub-modules.

## Highlights

- **Python provenance verification** -- Precompiled Python binaries from `astral-sh/python-build-standalone` can now be verified using GitHub Artifact Attestations, with downgrade protection in lockfiles.
- **Shim recursion guards** -- Two separate infinite-recursion bugs involving mise shims have been fixed, preventing fork bombs in devcontainer environments and when using `exec()` templates with mise-managed tools.
- **Go sub-module support** -- Deeply nested Go sub-modules that return no versions from `go list -versions` now correctly install with `@latest` instead of incorrectly resolving to a parent module's version.

## Added

- **Python GitHub Artifact Attestations** -- Precompiled Python binaries are now verified against GitHub Artifact Attestations from `astral-sh/python-build-standalone`, following the same pattern already used for Ruby. A new `python.github_attestations` setting (env: `MISE_PYTHON_GITHUB_ATTESTATIONS`) overrides the global `github_attestations` setting for Python specifically. When enabled, `mise lock` records `provenance = "github-attestations"` in lockfile entries, and `mise install` verifies downloaded tarballs. If a lockfile records provenance but verification is disabled at install time, the install fails with a downgrade-attack error. [#8820](https://github.com/jdx/mise/pull/8820) by @malept

  ```toml
  # settings.toml or mise.toml [settings]
  [python]
  github_attestations = true  # defaults to the global github_attestations value
  ```

- **Registry: svgo** -- `svgo` (SVG Optimizer) is now available as `npm:svgo`. [#8817](https://github.com/jdx/mise/pull/8817) by @3w36zj6

## Fixed

- **Shim infinite recursion with system shims on PATH** -- When tools are installed via `mise install --system` (e.g. in Docker/devcontainer images), a second shims directory is created at `MISE_SYSTEM_DATA_DIR/shims`. If both the user and system shims directories were on PATH, invoking a shim for a tool not in any config file would hang indefinitely. The PATH fallback now skips both shims directories and rejects any binary that canonicalizes to the mise binary itself. [#8816](https://github.com/jdx/mise/pull/8816) by @andrewthauer

- **Fork bomb from `exec()` templates, credential commands, and git credentials** -- Three subprocess-spawning code paths inherited mise shims in PATH. When the subprocess invoked a mise-managed tool (e.g. `gh auth token` in an `exec()` template or `credential_command`), the shim re-entered mise, triggering the same subprocess again -- causing infinite recursion. Observed as load average >1800 on affected systems. A new shared `path_env_without_shims()` helper now strips the shims directory from PATH in all three call sites. [#8802](https://github.com/jdx/mise/pull/8802) by @antonioacg

- **Go backend `--locked` mode** -- The Go backend was missing a `supports_lockfile_url() -> false` override, causing `mise install --locked` to fail for any go-backend tool since their lockfile entries never contain download URLs. [#8790](https://github.com/jdx/mise/pull/8790) by @palootcenas-outreach

- **Go deeply nested sub-module version resolution** -- `mise ls-remote` for deeply nested Go sub-modules (e.g. `github.com/go-kratos/kratos/cmd/kratos/v2`) would incorrectly resolve to the root module's versions. The version fetching logic now tries the exact tool path first and treats an empty version list as authoritative, falling back to `@latest` for installation instead of using a parent module's version. Results are now cached per module path. [#8823](https://github.com/jdx/mise/pull/8823) by @roele

- **Flutter version sorting** -- Fixed version sorting in the Flutter registry entry by stripping the `-stable` suffix before sorting, and switched to per-platform URL templates. [#8818](https://github.com/jdx/mise/pull/8818) by @roele

## New Contributors

- @antonioacg made their first contribution in [#8802](https://github.com/jdx/mise/pull/8802)
- @palootcenas-outreach made their first contribution in [#8790](https://github.com/jdx/mise/pull/8790)

**Full Changelog**: https://github.com/jdx/mise/compare/v2026.3.17...v2026.3.18