A AegiFlow
MEDIUMCVSS 5.5EPSS 0.2%

CVE-2026-54557

mise HTTP backend uses raw version path for install symlink destination

Published
2026-06-23
Modified
2026-07-21
EPSS percentile
7%
Aliases
GHSA-f94h-j2qg-fxw3
Sources
github-advisory

Summary

## Summary The mise HTTP backend builds its install symlink destination from the raw resolved version string for non-latest versions. Normal tool install paths use the sanitized version pathname, but the HTTP backend's symlink path uses the raw value. On Unix-like systems, if that version is an absolute path, `PathBuf::join` discards the intended mise installs root. A repository-controlled `.tool-versions` file can therefore make `mise install` create a symlink outside the mise install tree. With `bin_path`, the same issue can place an executable symlink under an attacker-selected absolute prefix, such as a developer-tool prefix that is later added to `PATH`. The reproducer below also models a CI/developer workflow where a later step executes a preexisting trusted command from a user-local `PATH` prefix. The absolute-version HTTP entry replaces that command with a symlink to downloaded HTTP content. A non-absolute version control does not replace the trusted `PATH` command. ## Affected Code In `src/backend/http.rs`, `create_install_symlink()` derives the destination path from raw `tv.version`: ```rust let version_name = if tv.version == "latest" || tv.version.is_empty() { &cache_key[..7.min(cache_key.len())] } else { &tv.version }; let install_path = tv.ba().installs_path.join(version_name); ``` `ToolVersion::tv_pathname()` already sanitizes `:` and `/` for filesystem version directory names, but this HTTP backend path does not use it. ## Impact Proven: - Outside-root symlink creation from a repository-controlled `.tool-versions` entry. - Executable symlink materialization under an attacker-selected absolute prefix when `bin_path` is configured. - The executable symlink can be run if that prefix's `bin` directory is on `PATH`. - Replacement of a preexisting command in a trusted `PATH` prefix in a local workflow-chain model, followed by execution of the replaced command by name. Not claimed: - `mise install` does not automatically execute the placed binary in the reproducer. - Windows drive-letter absolute paths are not claimed; the demonstrated impact is Unix-like path behavior. - Credential theft is not claimed. ## Why This Crosses A Boundary `.tool-versions` is an asdf-compatible project file and is parsed without the `mise.toml` trust gate used for configuration features that can execute code or affect the environment. Even if a project can choose tools to install, an install operation should keep HTTP backend materialization under the selected mise install/cache roots unless the user explicitly performs a trusted link or path operation. The HTTP backend documentation describes HTTP tool installations as symlinks under the mise installs directory, for example: ```text $MISE_DATA_DIR/installs/http-my-tool/1.0.0 -> $MISE_CACHE_DIR/http-tarballs/... ``` The observed behavior instead allows the project version string to choose an absolute install destination. ## Reproduction The script below performs three local checks: 1. It creates a `.tool-versions` entry whose HTTP backend version is an absolute path, then confirms that mise creates a symlink at that outside path. 2. It creates a second HTTP backend entry with `bin_path=bin` and confirms that mise places an executable symlink under an attacker-selected absolute prefix and that the symlink is executable when the prefix's `bin` directory is on `PATH`. 3. It creates a preexisting trusted command in a user-local `PATH` prefix, runs `mise install` from a project `.tool-versions` file, and confirms the later trusted command execution is replaced only in the absolute-version case. A non-absolute version control leaves the preexisting command in place. The script uses a loopback HTTP server and temporary directories only. ```sh #!/bin/sh set -eu if ! command -v mise >/dev/null 2>&1; then echo "mise must be on PATH" >&2 exit 1 fi if ! command -v python3 >/dev/null 2>&1; then echo "python3 must be on PATH for the loopback HTTP server" >&2 exit

Affected packages

EcosystemPackageAffected versionsFixed versions
rustmise2026.6.1

Remediation: Upgrade to 2026.6.1 or later.

References

Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.

CVE® is a registered trademark of The MITRE Corporation. CVE content reproduced under the CVE Terms of Use; copyright designation © MITRE.

EPSS scores provided by the FIRST.org Exploit Prediction Scoring System.