# mise permits untrusted local configuration to override default shell arguments

Untrusted .mise.toml [settings] can set shell interpreter args, which survive the global_only strip, so mise spawns attacker-controlled `sh -c 'PAYLOAD'` for tasks, postinstalls, exec and hooks.

- Payout: Research
- Severity: high
- Program: mise
- Found by: arpitjain099
- Disclosed: 2026-10-15
- CVE: CVE-2026-103929
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-g74g-rg72-j2p3
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-g74g-rg72-j2p3
- Tags: area:oss domain:oss impact:rce kind:research platform:ghsa sev:high tech:rust technique:incomplete-fix technique:source-review vuln:command-injection vuln:misconfiguration vuln:rce

**Target:** mise CLI settings preloader / shell interpreter invocation
**Root cause:** The CVE-2026-55448 fix strips only settings marked global_only, but the four *_default_*_shell_args settings (which choose the interpreter for every spawned command) were never marked global_only, so a local untrusted .mise.toml overrides them.
**Steps:**
1. Place `.mise.toml` in an untrusted repo with `[settings]` and `unix_default_inline_shell_args = "sh -c 'id > /tmp/mise_pwned'"`.
2. Victim cd's into the repo without trusting the file; preloader harvests [settings] regardless of trust store.
3. Victim runs any global/trusted task with no explicit shell, `mise install` of a tool with postinstall, a `{{ exec(...) }}` template, or a directory-enter hook.
4. mise builds `sh -c 'id > /tmp/mise_pwned' <realcommand>`, executing the payload with the real command demoted to $0.
**How found:** Reviewed the prior CVE-2026-55448 fix: strip_local_only_settings filters by meta.global_only, and only the three forge credential_command sinks were marked global_only. Checked settings.toml and found the four shell-args settings lacked the flag, then traced default_inline_shell and the exec/postinstall/task call sites to confirm the real command is appended after attacker args.
**Exploitation:** Attacker ships a malicious .mise.toml in a repo; when the victim later triggers any command mise spawns through the default shell (task, postinstall, tera exec, hook), the attacker's interpreter args run arbitrary commands as the victim.
**Insight:** When a fix is a per-field denylist, enumerate every other field of the same sink class (here: anything that selects an interpreter or executable) and check each for the flag; incomplete-fix regressions hide in the fields the original patch author didn't think of.

## Proof of concept (copied exactly from the original report)

**Malicious .mise.toml overriding inline shell args**

```
[settings]
unix_default_inline_shell_args = "sh -c 'id > /tmp/mise_pwned'"
```

