v2026.5.7
jdx/misev2026.5.7May 13, 2026by mise-en-dev
AI Summary
A round of correctness and performance fixes: vfox-managed tools no longer prompt your password manager on every shell hook, and version string parsing is hardened against shell injection.
Key Highlights
- GitHub tokens are now resolved lazily inside vfox plugins.
- `mise settings get` finally distinguishes typos from unset values.
- Security pass rejecting shell metacharacters in version strings.
New Features
- Lazy GitHub token resolution for vfox
- Settings typo distinction
- Security hardening for version strings
Full Release Notes
A round of correctness and performance fixes: vfox-managed tools no longer prompt your password manager on every shell hook, `mise upgrade` stops double-printing its summary, `mise settings get` finally distinguishes typos from unset values, and conda installs that pulled in `adwaita-icon-theme` are unstuck. Plus a security pass that hardens version-string parsing against shell injection.
## Fixed
- **(vfox)** GitHub tokens are now resolved lazily inside Lua plugins. Previously, `mise hook-env`, `mise activate`, `mise completion`, and even `mise --help` would call `github.credential_command` for every installed vfox tool — potentially unlocking a password manager on every prompt. The resolver is now only invoked when a Lua plugin actually issues an HTTP request to a GitHub API URL, e.g. during an install ([#9816](https://github.com/jdx/mise/pull/9816)) by @jdx. Fixes [#9797](https://github.com/jdx/mise/issues/9797).
- **(upgrade)** `mise upgrade` (and `mise up`) no longer prints the installed-tools block twice when an upgrade also needs to uninstall an older version. The shared progress-job registry is now cleared after each phase so the subsequent uninstall renders cleanly ([#9779](https://github.com/jdx/mise/pull/9779)) by @jdx. Fixes [#9774](https://github.com/jdx/mise/issues/9774).
- **(settings)** `mise settings get` distinguishes between a known setting that hasn't been set and a typo:
```sh
$ mise settings get python.compile
mise ERROR Setting [python.compile] is not set
$ mise settings get not.a.real.setting
mise ERROR Unknown setting: not.a.real.setting
```
Previously both returned `Unknown setting`, since `Option<T>` fields skipped by TOML serialization were indistinguishable from missing keys ([#9818](https://github.com/jdx/mise/pull/9818)) by @jdx.
- **(backend)** Several backends (`aqua`, `github`/`gitlab`/`forgejo`, `http`, `s3`, `ubi`, `vfox`, `conda`, Windows `npm`) reported `bin-paths` pointing at the concrete resolved install dir (e.g. `installs/tiny/1.0.0/...`) instead of the stable runtime symlink for the requested label (e.g. `installs/tiny/latest/...`). A new `runtime_path_for_install_path` helper remaps backend-discovered absolute paths onto the runtime path while leaving explicit relative `bin_path` values alone ([#9606](https://github.com/jdx/mise/pull/9606)) by @risu729.
- **(conda)** `mise use -g imagemagick` (and other tools pulling in `adwaita-icon-theme`) failed with `conda solve failed: encountered duplicate records for adwaita-icon-theme-40.1.1-...`. rattler-solve detects duplicates by `DistArchiveIdentifier` rather than URL, so when conda-forge served the same archive under multiple CDN URLs, the existing URL-based dedup wasn't enough. Dedup now uses `r.identifier`, the exact key the solver uses ([#9831](https://github.com/jdx/mise/pull/9831)) by @jdx. Fixes [#9829](https://github.com/jdx/mise/discussions/9829).
## Added
- **(github)** `github.credential_command` now runs through the configured default inline shell (instead of hardcoded `sh -c`) and is invoked with `MISE_CREDENTIAL_HOST` and `MISE_CREDENTIAL_PROVIDER` in the environment. The deprecated `$1` / `${1}` hostname positional argument continues to work for sh-compatible shells (`ash`, `bash`, `dash`, `ksh`, `sh`, `zsh`); a deprecation warning lands in `2026.11.0` and removal is planned for `2027.11.0` ([#9664](https://github.com/jdx/mise/pull/9664)) by @risu729.
## Performance
- **(aqua)** The baked aqua standard-registry package and alias lookup tables are now generated as static `phf::Map`s at build time via `phf_codegen`, instead of lazy runtime `HashMap`s. Warmed lookup is comparable, but first-use no longer allocates ~115 KiB of heap or builds a 2,179-entry bucket table ([#9763](https://github.com/jdx/mise/pull/9763)) by @risu729.
- **(task)** When `task.source_freshness_hash_contents = true`, mise now caches each source file's blake3 hash keyed by `(size, mtime_secs, mtime_nanos)` — git's stat-info trick — in a per-task file under `STATE/task-sources/`. Unchanged files are skipped on subsequent runs; entries for files removed from `sources` are pruned automatically ([#9819](https://github.com/jdx/mise/pull/9819)) by @jdx. See [discussion #9802](https://github.com/jdx/mise/discussions/9802).
## Security
- **Reject shell metacharacters in version strings at the `ToolRequest` boundary** ([#9814](https://github.com/jdx/mise/pull/9814)) by @jdx. `ToolRequest::new` now validates `version`, `prefix`, `ref/*`, `sub-*`, and `path:` requests, rejecting `$`, backticks, quotes, `\`, control chars, and `..` traversal. This single change neutralizes the CRITICAL RCE class flagged against `vfox-ag`, `vfox-bfs`, `vfox-bpkg`, `vfox-chezscheme`, `vfox-redis`, `vfox-yarn`, and shell-injection findings on `clickhouse`, `leiningen`, `pipenv`, `poetry`, `azure-functions-core-tools`, `carthage`, and `android-sdk`, since no Lua hook can observe a hostile `ctx.version` / `ctx.rootPath`. Real-world strings like `1.2.3-beta`, `lts/hydrogen`, `3.12.0a1`, and `nightly` continue to validate. The PR also tightens `workflow_dispatch` input validation in the COPR, PPA, npm-publish, and Docker workflows.
## Registry
- Replace unsupported `exe = ...` options across ~30 GitHub/GitLab registry entries (`astro`, `babashka`, `coursier`, `glab`, `odin`, `openbao`, `purescript`, and many more) ([#9587](https://github.com/jdx/mise/pull/9587)) by @risu729. Two entries gained real config to fix Linux installs:
- `solidity` now uses `bin = "solc"` so the installed binary matches the upstream `solc-static-linux` asset.
- `sourcery` now uses `format = "tar.gz"` because the upstream Linux asset is gzip-compressed despite its `.tar.xz` filename.
- Update `pi` to `earendil-works/pi` ([#9792](https://github.com/jdx/mise/pull/9792)) by @garysassano.
## Documentation
- **(aliases)** Fix the Aliased Versions example and drop the stale asdf callout ([#9830](https://github.com/jdx/mise/pull/9830)) by @jdx.
**Full Changelog**: https://github.com/jdx/mise/compare/v2026.5.6...v2026.5.7
## 💚 Sponsor mise
mise is built by [@jdx](https://github.com/jdx) under [**en.dev**](https://en.dev) — an independent studio making developer tooling (mise, [aube](https://aube.en.dev/), and more). Development is funded by sponsors.
If mise saves you or your team time, please consider sponsoring at [en.dev](https://en.dev). Individual and company sponsorships keep mise fast, free, and independent.