v2026.10.13

jdx/misev2026.10.13Oct 17, 2026by mise-en-dev

Upgrading?

AI Summary

This release introduces a security enhancement to ignore `[settings]` in untrusted project configurations until explicitly trusted. It also adds support for per-version-range backend options in the registry and template rendering for command wrappers and bootstrap repositories. Additionally, it resolves various bugs related to lockfiles, task execution, and multi-version tool options.

Key Highlights

  • Security: `[settings]` in untrusted project configs is now ignored to prevent malicious settings from redirecting downloads or build commands.
  • Registry: Added support for per-version-range backend options, allowing different configuration settings for specific tool versions.
  • Wrappers: Command wrapper values (`command`, `args`, `env`) now support template rendering using `vars` and `env`.
  • Bootstrap: `[bootstrap.repos]` now supports templated `url` and `ref` for dynamic repository cloning.
  • Bug Fixes: Fixed lockfile recording issues on Windows, task hanging problems, and per-version tool option application.

Breaking Changes

  • Untrusted project configs can no longer change settings (e.g., `node.mirror_url`, `python.pyenv_repo`) until the project is trusted.

New Features

  • Per-version-range backend options in the registry.
  • Command wrapper values render as templates.
  • [bootstrap.repos] supports templated URLs and refs.
  • New `{{ system_brew_prefix }}` template variable.
  • vfox `PreInstall` hooks support `headers` table.
  • `mise doctor` reports stale shims on Windows.

Full Release Notes

mise now ignores `[settings]` in a project config until you trust it. This release also adds per-version-range backend options to the registry and template support for command wrappers and `[bootstrap.repos]`. It fixes several bugs in lockfiles, tasks and multi-version tool options.

## Security

- **`[settings]` from untrusted project configs is ignored.** Before, a cloned repo's `mise.toml` could change settings as soon as mise found it, with no trust prompt. That included settings that redirect downloads or feed build commands, such as `node.mirror_url`, `python.pyenv_repo` and `ruby.precompiled_url`. These settings now apply only after `mise trust`, like `[env]`, `[hooks]` and `[tools]` options already did. Trusted projects, global and system config, environment variables and CLI flags work as before. Commands that trust the active config implicitly (`mise run`, `mise exec`, `mise install`) reload settings after trusting it, so the project's settings still apply to that same command. Settings files are now parsed once per load. [#14538](https://github.com/jdx/mise/pull/14538), [#14553](https://github.com/jdx/mise/pull/14553) (@jdx)

  For example, if an untrusted repo sets `[settings.python] pyenv_repo` to its own URL, `mise settings get python.pyenv_repo` returns the default pyenv repository until you run `mise trust`.

- mise's own `zip` dependency moved to 9.x, which fixes GHSA-4684-h2q9-2vcp. Older versions applied Unix permissions through extracted symlinks without checking that the target stayed inside the destination. mise uses this code to extract downloaded `.zip` tool archives. [#14577](https://github.com/jdx/mise/pull/14577) (@jdx)

## Added

- **One registry backend can carry different options for each version range.** A registry entry can list the same backend more than once, each time with its own `min_version`/`max_version` and `options`. Tools whose release assets changed at some version can then stay on one backend. Two entries can't give the same version different options unless their `platforms` don't overlap. Table syntax such as `tool = { version = "1.4.0" }` now takes its registry defaults from the entry that version selects. Older mise releases apply only the first entry's options to every version. [#14543](https://github.com/jdx/mise/pull/14543) (@jdx)

  ```toml
  backends = [
    { full = "github:example/tool", min_version = "2.0.0", options = { asset_pattern = "tool-v2-*" } },
    { full = "github:example/tool", max_version = "2.0.0", options = { asset_pattern = "tool-*" } },
  ]
  ```

- **`mise ls-remote` lists every version range of a registry tool.** When a tool's backends serve different version ranges, mise now lists each range from the backend that serves it. Before, it listed only the first backend's range. For example, `mise ls-remote hk` now starts at 0.1.4 instead of 1.58.1. Explicit backends, overrides, `--all` and `--strict-metadata` behave as before. [#14544](https://github.com/jdx/mise/pull/14544) (@jdx)
- **Command wrapper values render as templates.** `command`, `args` and `env` in `[wrappers]` can use `vars`, `env` and the usual template functions. `tools` and `config_root` are not available. A command that renders blank is an error. Use `{% raw %}` to keep literal braces, such as Docker's `{{.Names}}`. [#14565](https://github.com/jdx/mise/pull/14565) (@jdx)

  ```toml
  [wrappers.foo]
  command = "foo-real"
  args = ["--mode={{ vars.mode }}"]
  env = { FOO_HOME = "{{ [xdg_data_home, 'foo'] | join_path }}" }
  ```

- **`[bootstrap.repos]` supports templated `url`/`ref` and clone options.** `url` and `ref` render from `[vars]` or the process environment. Values from a config's `[env]` table are not available. `filter`, `depth` and `submodules = true` are passed to the first `git clone` as `--filter`, `--depth` and `--recurse-submodules`. Existing checkouts are left as they are. `depth` can't be combined with a commit SHA or a `refs/…` ref. [#14548](https://github.com/jdx/mise/pull/14548) (@jdx, @ovidiubuligan)

  ```toml
  [bootstrap.repos]
  "~/src/large" = { url = "git@github.com:example/large.git", ref = "{{ vars.branch }}", filter = "blob:none", depth = 1 }
  ```

- **`{{ system_brew_prefix }}` template variable.** It resolves to the Homebrew prefix that `mise bootstrap` installs into: `/opt/homebrew` on macOS and `/home/linuxbrew/.linuxbrew` on Linux, or the value of `MISE_SYSTEM_BREW_PREFIX`. It does not detect a Homebrew install somewhere else. `[bootstrap.user].login_shell` now renders templates too, so `login_shell = "{{ system_brew_prefix }}/bin/zsh"` works. [#14572](https://github.com/jdx/mise/pull/14572), [#14570](https://github.com/jdx/mise/pull/14570) (@jdx)
- **vfox `PreInstall` hooks can return a `headers` table** next to `url` and `sha256`. Plugins can now download private or token-gated artifacts through the normal install path, which handles checksums, retries and lockfile URLs. Headers are sent only to the origin of `url`, are dropped on cross-origin redirects, are redacted in debug output and are never written to `mise.lock`. An explicit `Authorization` header overrides netrc and the automatic GitHub token. [#14531](https://github.com/jdx/mise/pull/14531) (@jdx)
- **`mise doctor` reports a stale `mise-shim.exe` on Windows.** In `windows_shim_mode = "exe"`, shims are copies of the `mise-shim.exe` that sits beside `mise.exe`. If that template is older than mise, or has no version tag (every template built before this release), `mise doctor` reports it and `mise reshim` warns. To fix it, update mise with the package manager that installed it, or run `mise self-update`, and then run `mise reshim --force`. [#14586](https://github.com/jdx/mise/pull/14586) (@jdx)

## Fixed

- **Lockfiles**
  - Running `mise lock` on Windows now records `ruby` entries for Windows, Linux and macOS platforms. Before, it skipped them, and `mise install --locked` then failed. [#14520](https://github.com/jdx/mise/pull/14520), [#14529](https://github.com/jdx/mise/pull/14529) (@jdx)
  - Commands that rewrite `mise.lock` without locking again, such as `mise link`, no longer delete other platforms' option variants (for example, per-platform `asset_pattern` entries). [#14519](https://github.com/jdx/mise/pull/14519) (@jdx)
  - A `mise link` for one version of a tool no longer makes `mise install --locked` fail for that tool's other versions. A link now bypasses the lockfile only when the requested version could select it. [#14539](https://github.com/jdx/mise/pull/14539) (@jdx)
  - `mise install --locked` for Java no longer fetches the mise-java catalog when `mise.lock` already has the download URL, so locked installs work in air-gapped or proxied environments. [#14534](https://github.com/jdx/mise/pull/14534) (@jdx)
- **Tasks and shims**
  - `mise run` no longer hangs when parallel tasks need to install the same tool. [#14536](https://github.com/jdx/mise/pull/14536) (@jdx)
  - Running `mise install` inside a task no longer removes the shims for that task's `lazy` tools. [#14533](https://github.com/jdx/mise/pull/14533) (@jdx)
  - Task hooks (such as `postinstall = { task = "setup" }`) and `watch_files` task hooks now run with mise even when a tool shim triggered them. Before, they could fail with errors like `jq: Unknown option --cd`. [#14550](https://github.com/jdx/mise/pull/14550) (@jdx, @alitas)
  - `mise watch` exits quietly with status 130 when you interrupt watchexec with Ctrl+C, instead of printing an error. [#14541](https://github.com/jdx/mise/pull/14541) (@jdx)
- **Per-version tool options**
  - When a `github:`, `gitlab:` or `forgejo:` tool lists several versions in config, each version now installs with its own options. Before, an option such as `rename_exe` set only on the first entry applied to every version. [#14537](https://github.com/jdx/mise/pull/14537) (@JamBalaya56562)
  - `vfox:` plugin hooks now receive only the options configured for the version they handle. [#14562](https://github.com/jdx/mise/pull/14562) (@JamBalaya56562)
- `mise install` now restores `cargo`, `rustc` and the host's `rust-std` when they are missing from a Rust toolchain with the `minimal` or `default` profile. Before, mise reported such a toolchain as installed. [#14525](https://github.com/jdx/mise/pull/14525) (@JamBalaya56562, @risu729)
- The uv, pip and poetry deps providers now run again after mise recreates a deleted venv in a later process. Before, the new venv stayed empty. [#14532](https://github.com/jdx/mise/pull/14532) (@halms)
- vfox plugins now report an error, instead of crashing mise, when the HTTP client can't be built (for example, when no CA certificates are installed). [#14576](https://github.com/jdx/mise/pull/14576) (@JamBalaya56562)
- MCP resource read errors now include the underlying cause, such as the untrusted-config message and its `mise trust` hint. [#14566](https://github.com/jdx/mise/pull/14566) (@diogochaves)

## Registry

- `xcsift` 1.7.0 and later installs from signed Packslip releases and now supports Linux x64 as well as macOS ARM64. [#14540](https://github.com/jdx/mise/pull/14540) (@jdx)
- `protoc-gen-connect-go` 2.x now installs from the `/v2` Go module path, and 1.x versions keep working. [#14545](https://github.com/jdx/mise/pull/14545) (@jdx)
- Added `rea` (`npm:rea-agents`). [#14421](https://github.com/jdx/mise/pull/14421) (@phucisstupid)

## Documentation

- The docs now state that OpenTelemetry export and spinel installs require `experimental = true`. [#14552](https://github.com/jdx/mise/pull/14552) (@ZainnQureshii)

## New Contributors

* @phucisstupid made their first contribution in [#14421](https://github.com/jdx/mise/pull/14421)
* @diogochaves made their first contribution in [#14566](https://github.com/jdx/mise/pull/14566)
* @ZainnQureshii made their first contribution in [#14552](https://github.com/jdx/mise/pull/14552)
* @fang2hou made their first contribution in [#14551](https://github.com/jdx/mise/pull/14551)

**Full Changelog**: https://github.com/jdx/mise/compare/v2026.10.12...v2026.10.13

## 💚 Sponsor mise

mise is built and maintained by [@jdx](https://github.com/jdx), an open source developer at [**entire.io**](https://entire.io/), the title sponsor of his open source work.

If mise saves you or your team time, please consider becoming an [individual or company sponsor](https://jdx.dev/sponsors.html). Your support funds ongoing development and helps keep mise fast, free, and independent.

Related Repositories