jdx/mise · error
is disabled in safe mode (MISE_SAFE=1) See…
Error message
{operation} is disabled in safe mode (MISE_SAFE=1)
See https://mise.jdx.dev/configuration/settings.html#safe What it means
Safe mode (`MISE_SAFE=1`) hard-blocks any operation that would execute code controlled by project configuration (hooks, postinstall scripts, task run commands, templates). `Settings::ensure_not_safe` is called before such operations and fails loudly rather than silently executing untrusted code. This is an intentional security boundary, not a bug.
Solutions
- If you trust the repository, unset the variable: `unset MISE_SAFE` (or `MISE_SAFE=0`) and re-run.
- Use `mise trust` after reviewing the config, then run without safe mode.
- In CI/agent environments, pre-install tools from trusted sources before enabling MISE_SAFE=1.
Example fix
# before MISE_SAFE=1 mise install # Error: install is disabled in safe mode # after mise trust && MISE_SAFE=0 mise install
Defensive patterns
Strategy: validation
Validate before calling
# shell: check safe mode before invoking mise commands that run code if [ "$MISE_SAFE" = "1" ]; then echo "safe mode blocks this operation"; fi
Try / catch
# shell: explicitly opt out only for trusted repos if [ "$MISE_SAFE" = "1" ]; then mise trust && MISE_SAFE=0 mise install || exit 1 fi
Prevention
- Only set MISE_SAFE=1 in environments handling untrusted checkouts; unset it for your own projects.
- Run `mise trust` after reviewing a repo's config before disabling safe mode.
- In CI, split the job: install tools in a trusted step, analyze untrusted code with MISE_SAFE=1.
When it happens
Trigger: Running mise with MISE_SAFE=1 (used by agents/CI when checking out untrusted repos) and triggering an operation that calls `Settings::ensure_not_safe`, e.g. install with postinstall hooks, task execution, or env template evaluation that runs code.
Common situations: CI jobs or AI agents that install tools from an untrusted checkout with safe mode set; running `mise install` on a fresh clone while MISE_SAFE=1 is exported in the shell profile.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- bootstrap secret ' ' has invalid environment variable name
- install_mise must not contain '..
- invalid repository origin
- no trusted public keys available for verification
- `ref` must not start with `-`
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/ac8dc145c6d05750.
Report an issue: GitHub.
Appendix: source
Thrown at src/config/settings.rs:1905
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(crate) 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 533346cc37)