v2026.7.12
jdx/misev2026.7.12Jul 23, 2026by mise-en-dev
AI Summary
This release introduces safe mode for running against untrusted config, enables node-free npm package resolution, and replaces external tools like skopeo with a built-in OCI registry client.
Key Highlights
- New `MISE_SAFE=1` mode makes mise inert to prevent code execution from untrusted config files.
- The `npm:` backend no longer requires Node.js to resolve or install packages.
- Built-in OCI registry client for `mise oci push` with blob dedup, retries, and multi-arch support.
Breaking Changes
- The `mise oci push --tool` flag has been removed.
- Node/Swift signature verification now always runs when enabled.
- The unreleased `npm.use_npm_view` setting is replaced by `npm.shell_out`.
New Features
- Safe mode configuration for CI/automation
- Lockfile-only PR generation with `--dry-run`
- In-process npm installation via embedded aube
- OCI layer reuse and multi-arch image indexes
- Native signature verification dropping external gpg dependency
Full Release Notes
This release centers on running mise safely against untrusted config, shipping node-free `npm:` version resolution and installs, and replacing external tools (skopeo/crane, gpg) with built-in, dependency-free implementations. Along the way it fixes a `prefer_offline` timeout regression, several config/env correctness issues, and platform-specific problems on Windows and macOS.
## Highlights
- New `MISE_SAFE=1` mode turns mise into an inert config reader so automation (CI, Renovate) can run `mise lock --bump` against untrusted branches without trust prompts or arbitrary code execution.
- The `npm:` backend no longer needs node or npm installed to resolve or install packages — version metadata is fetched over HTTP and installs run in-process via the embedded aube package manager.
- `mise oci push` gained a full built-in registry client: no more skopeo/crane, with blob dedup, chunked uploads, retries, cross-repo mounts, layer reuse from prior images, and multi-arch image indexes.
## Added
- **Safe mode:** a new global-only `safe` setting (`MISE_SAFE=1`) makes mise refuse or ignore anything that would let project config execute code or inject environment. Blocked (with errors): template `exec()`/`read_file()`, `_.source`, hooks, tasks, asdf plugin scripts, and plugin installs. Ignored: project `[env]`, `_.path`, `_.file`, `[shell_alias]`, and `[settings]`. HTTP-based version resolution, lockfile refresh/bump, and already-installed/embedded plugins keep working. Because a config loaded this way is inert, safe mode also skips the trust requirement. ([#11146](https://github.com/jdx/mise/pull/11146), [#11151](https://github.com/jdx/mise/pull/11151) by @jdx)
```sh
MISE_SAFE=1 mise lock --bump --dry-run --json # detect updates with zero code execution, no trust needed
```
- **`mise lock --bump`:** advance fuzzy lockfile selectors (`latest`, `lts`, prefixes like `"20"`) to the newest matching remote versions without installing anything and without touching `mise.toml`. Exact pins stay put. Pairs with `--json` and `--dry-run` for a CI job that opens lockfile-only PRs. ([#11145](https://github.com/jdx/mise/pull/11145) by @jdx)
```console
$ mise lock --bump --dry-run --json
[{ "name": "node", "backend": "core:node", "old_versions": ["22.14.0"], "new_versions": ["22.15.0"] }]
```
- **Node-free `npm:` backend:** `mise ls-remote npm:*` and `latest` resolution now query the npm registry directly over HTTP, and installs run in-process through the embedded aube package manager. node is only needed to *run* installed tools (and their lifecycle scripts), not to install them. User `~/.npmrc`, scoped registries, auth, and `minimum_release_age` are honored. A new `npm.shell_out` setting (`MISE_NPM_SHELL_OUT`) routes both metadata and installs through the npm CLI for setups relying on npm-only config like `cafile` or client certs. ([#11147](https://github.com/jdx/mise/pull/11147), [#11149](https://github.com/jdx/mise/pull/11149) by @jdx)
- **Built-in OCI registry client:** `mise oci push` no longer requires skopeo or crane. It uses an in-tree OCI Distribution client that uploads only blobs the registry is missing, resolves credentials the way docker/podman do (`docker login`/`podman login` is all the setup needed), and answers registry auth challenges so private base-image pulls via `--from` also work. `mise oci run --engine docker` now streams the image into `docker load` instead of needing skopeo. The `--tool` flag was removed. ([#11132](https://github.com/jdx/mise/pull/11132) by @jdx)
- **OCI push robustness:** large layers upload in 64 MiB chunks, transient failures retry with mise's standard backoff, base layers are mounted cross-repo (`?mount=`) when they already live on the destination registry (zero bytes transferred), and pushes/pulls now show byte progress. A new `oci.insecure_registries` setting opts non-loopback registries into plain HTTP. ([#11141](https://github.com/jdx/mise/pull/11141) by @jdx)
- **OCI layer reuse:** `mise oci push` reuses unchanged tool layers from the previously pushed image (or `--cache-from REF`), skipping the tar/gzip build entirely — reused tools don't even need to be installed locally. `--no-cache` forces a full rebuild. ([#11142](https://github.com/jdx/mise/pull/11142) by @jdx)
- **Multi-arch OCI images:** `mise oci push --update-index` points a tag at an OCI image index and upserts the current platform while preserving entries pushed by other architectures, so one runner per arch can assemble a multi-arch tag. ([#11144](https://github.com/jdx/mise/pull/11144) by @jdx)
- **Built-in signature verification:** Node.js and Swift download signatures are now verified in-process with the pure-Rust rPGP crate against the bundled keyrings, dropping the external `gpg` binary dependency. Note: previously, if `gpg` was missing and the setting was unset, verification was silently skipped; now verification always runs when enabled — opt out with `gpg_verify = false`. ([#11148](https://github.com/jdx/mise/pull/11148) by @jdx)
- **Relative bootstrap repo paths:** `[bootstrap.repos]` destination keys can now be relative paths, resolved against the declaring project's root (with guards preventing escape outside the project tree), making a project's `mise.toml` portable across machines. ([#11155](https://github.com/jdx/mise/pull/11155) by @lilienblum)
## Fixed
- **http:** `mise lock`, `ls-remote`, `outdated`, and `upgrade` no longer get capped to a single 3s no-retry attempt when `prefer_offline` is set — they honor the configured `fetch_remote_versions_timeout` and retry budget again, fixing spurious timeouts. Interactive fast paths keep their bounded behavior. ([#11190](https://github.com/jdx/mise/pull/11190) by @jdx)
- **lock:** unfiltered `mise lock` no longer prunes OS-restricted tool entries (e.g. `os = ["macos"]`) when run on a platform that doesn't target them, keeping shared lockfiles stable across platforms. ([#11175](https://github.com/jdx/mise/pull/11175) by @jdx)
- **env:** values loaded from `_.file` env files now resolve references to variables defined in earlier files or `[env]` blocks instead of collapsing to empty, fixing flaky dotenv behavior. ([#11158](https://github.com/jdx/mise/pull/11158) by @Marukome0743)
- **env:** `[env] _.source` now works on Windows by resolving a real POSIX bash (Git Bash / MSYS2, honoring `MISE_BASH_PATH`) instead of the WSL launcher or a missing `bash.exe`, and correctly filters MSYS runtime noise and converts prepended PATH entries back to Windows form. ([#11097](https://github.com/jdx/mise/pull/11097) by @JamBalaya56562)
- **config:** `trusted_config_paths` (`MISE_TRUSTED_CONFIG_PATHS`) now overrides configs previously added to the ignore list, so a settings-trusted config is actually discovered and loaded. ([#11152](https://github.com/jdx/mise/pull/11152) by @JamBalaya56562)
- **config:** `env`/`vars` array parsing is now consistent — accidental array forms for `vars` and task `env`/`vars` are rejected with clear errors, while the intentional `[[env]]` and directive-level arrays (`_.source`, `_.file`, `_.path`) remain supported. ([#11060](https://github.com/jdx/mise/pull/11060) by @risu729)
- **config:** `mise config set` no longer panics when descending into a non-table value. ([#11153](https://github.com/jdx/mise/pull/11153) by @Marukome0743)
- **config:** clearer warnings for unsupported semver ranges. ([#11176](https://github.com/jdx/mise/pull/11176) by @risu729)
- **hook-env:** entering a directory with an untrusted config now prints a single concise warning (`... is not trusted, run 'mise trust' to enable it`) instead of the full error chain. Explicit commands still show the full trust error and prompt. ([#11159](https://github.com/jdx/mise/pull/11159) by @lilienblum)
- **activate:** `mise activate zsh` no longer hangs non-interactive login shells under Rosetta — a v2026.7.11 regression where env-state snapshotting autoloaded the `zsh/parameter` module via `dlopen`. ([#11188](https://github.com/jdx/mise/pull/11188) by @jdx)
- **brew-cask:** case-insensitive app bundle lookup (fixing casks like `yaak`) and correct resolution of preflight-generated wrapper scripts on the extract stage (fixing `vlc`). ([#11164](https://github.com/jdx/mise/pull/11164) by @donbeave)
- **brew:** cask binaries can symlink into `/usr/local` on arm64. ([#11174](https://github.com/jdx/mise/pull/11174) by @jdx)
- **backend:** qualified prerelease suffixes are now detected correctly. ([#11179](https://github.com/jdx/mise/pull/11179) by @risu729)
- **completions:** avoid a network lookup during usage completion. ([#11169](https://github.com/jdx/mise/pull/11169) by @jdx)
- **link:** clear a stale incomplete marker when linking a tool. ([#11150](https://github.com/jdx/mise/pull/11150) by @Marukome0743)
- **shim:** unresolved Windows exe-shim dispatch (e.g. a project-scoped tool run outside the project) now shows the actionable "no version is set" guidance instead of an opaque "cannot find binary path". ([#11189](https://github.com/jdx/mise/pull/11189) by @jdx)
- **vfox:** preserve inner quotes when a vfox Lua command dispatches through `cmd.exe` on Windows, fixing commands such as the Yarn 2+ install flow. ([#11166](https://github.com/jdx/mise/pull/11166) by @finalchild)
- **github/gitlab/forgejo:** statically-linked `linux-musl` assets are now considered a fallback for Android/Termux when a package publishes no Android-specific asset, so tools like starship, bat, and hk can install there. ([#10730](https://github.com/jdx/mise/pull/10730) by @bltavares)
- **deps:** avoid installing tools during dry runs, and enforce the experimental gate for task providers. ([#11016](https://github.com/jdx/mise/pull/11016), [#11177](https://github.com/jdx/mise/pull/11177) by @risu729)
## Documentation
- Document environment-variable backing for file-task arguments and flags, including CLI/env/default precedence. ([#11165](https://github.com/jdx/mise/pull/11165) by @zeitlinger)
## Breaking Changes
- `mise oci push --tool` has been removed. Use `mise oci build -o ./img` followed by `skopeo copy` if you need the old escape hatch. ([#11132](https://github.com/jdx/mise/pull/11132))
- Node/Swift signature verification now always runs when enabled (external `gpg` is no longer required). If you relied on a missing `gpg` binary to skip verification, set `gpg_verify = false` explicitly. ([#11148](https://github.com/jdx/mise/pull/11148))
- The unreleased `npm.use_npm_view` setting is replaced by `npm.shell_out` (`MISE_NPM_SHELL_OUT`). ([#11149](https://github.com/jdx/mise/pull/11149))
## New Contributors
- @donbeave made their first contribution in [#11164](https://github.com/jdx/mise/pull/11164)
- @lilienblum made their first contribution in [#11159](https://github.com/jdx/mise/pull/11159)
**Full Changelog**: https://github.com/jdx/mise/compare/v2026.7.11...v2026.7.12
## 💚 Sponsor mise
mise is maintained by [@jdx](https://github.com/jdx), an open source developer for [**entire.io**](https://entire.io), the title sponsor of the [jdx.dev](https://jdx.dev) open source tools. Development is funded by sponsors.
If mise saves you or your team time, please consider sponsoring at [jdx.dev](https://jdx.dev/sponsors.html). Individual and company sponsorships keep mise fast, free, and independent.