jdx/mise · error · eyre::Report
{operation} is disabled in safe mode (MISE_SAFE=1) See https
Error message
{operation} is disabled in safe mode (MISE_SAFE=1)
See https://mise.jdx.dev/configuration/settings.html#safe What it means
`Settings::ensure_not_safe` (src/config/settings.rs:1426) enforces safe mode (`MISE_SAFE=1`): a security boundary that fails loudly before any operation which would execute code controlled by project configuration (remote/git task files, config-driven commands). Blocked operations must never silently fall back to something else that executes, hence a hard error with a docs link.
Source
Thrown at src/config/settings.rs:1439
return Settings::get().safe;
}
// Settings not loaded (e.g. the config parse pass after Config::reset).
// Use the value cached from the last full load, which captures `safe`
// set via global config; before any load, fall back to the env var.
match LAST_SAFE.load(Ordering::Relaxed) {
0 => false,
1 => true,
_ => crate::env::var_is_true("MISE_SAFE"),
}
}
/// Errors when safe mode (`MISE_SAFE=1`) is enabled. Call this before any
/// operation that would execute code controlled by project configuration.
/// Safe mode is a security boundary: blocked operations must fail loudly,
/// never silently fall back to something that executes.
pub fn ensure_not_safe(operation: &str) -> Result<()> {
if Settings::safe_mode() {
bail!(
"{operation} is disabled in safe mode (MISE_SAFE=1)\nSee https://mise.jdx.dev/configuration/settings.html#safe"
);
}
Ok(())
}
}
fn redacted_settings_for_debug(settings: &Settings) -> Settings {
let mut debug_settings = settings.clone();
if debug_settings.task.cache.remote_token.is_some() {
debug_settings.task.cache.remote_token = Some("[redacted]".to_string());
}
debug_settings
}
fn remove_empty_nested_settings(table: &mut toml::Table, prefix: &str) {
table.retain(|key, value| {
let path = if prefix.is_empty() {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Re-run with safe mode off for this command: `MISE_SAFE=0 mise <cmd>` (or unset MISE_SAFE)
- Find and remove the stray `MISE_SAFE=1` export in shell profiles, CI env, or wrapper scripts
- If safe mode is intentional, do the blocked step manually outside mise (e.g. clone the repo and reference local task files)
- Read the linked settings docs section to know exactly which operations are blocked before scripting around them
Example fix
# before $ export MISE_SAFE=1 && mise run build # blocked # after $ unset MISE_SAFE && mise run build # or scoped: $ MISE_SAFE=0 mise run build
Defensive patterns
Strategy: validation
Validate before calling
# guard scripts that need project-config execution
if [ "${MISE_SAFE:-0}" = "1" ]; then
echo "MISE_SAFE=1 blocks this mise operation; unset it or MISE_SAFE=0" >&2; exit 1
fi
mise run build Try / catch
In wrappers, detect the `disabled in safe mode` message and branch: either re-exec with MISE_SAFE=0 after explicit approval, or report that the step must run outside safe mode — never silently skip it.
Prevention
- Scope MISE_SAFE to the exact untrusted commands instead of exporting it globally
- Keep an audited list of which operations safe mode blocks (docs link in the error) when writing CI
- For untrusted repos, clone and inspect task files manually rather than toggling safe mode off
When it happens
Trigger: Running a guarded operation — e.g. resolving/loading `git::` remote task files via `resolve_git_url_to_path` — while `MISE_SAFE` is `1` (or any value `env::var_is_true` accepts, since only `0` forces off).
Common situations: Hardened CI images or corporate shells that export MISE_SAFE globally; auditing an untrusted repo with safe mode and then running ordinary commands in the same shell; wrapper scripts that set MISE_SAFE and never unset it.
Related errors
- content-level SLSA verification rejected unsafe archive path
- failed to apply landlock restrictions: {status:?}
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/ac8dc145c6d05750.
Report an issue: GitHub.