jdx/mise · error
brew-cask: refusing installer executable outside trusted…
Error message
brew-cask: refusing installer executable outside trusted installer roots: {} What it means
For casks with an installer artifact, mise validates that the staged installer executable resolves to a path strictly within the trusted installer roots (via `staged_relative_path` against the stage). If the configured executable path escapes the stage, mise refuses to run it, preventing a cask from executing arbitrary binaries outside the controlled extraction area.
Solutions
- Fix the cask's installer `executable` to a path relative to the staged payload (e.g. "Foo Installer.app/Contents/MacOS/foo")
- Update the cask to the latest version in case the executable location changed upstream
- Verify the cask source is trusted; re-fetch rather than hand-editing
- Report the cask to maintainers if a stock cask triggers this
Example fix
// before // executable: "/usr/bin/osascript" // after // executable: "scripts/install.scpt" # within the staged payload
Defensive patterns
Strategy: validation
Validate before calling
let stage = fs::canonicalize(stage_dir)?;
let exe = stage.join(&installer.executable);
let resolved = fs::canonicalize(&exe)?;
if !resolved.starts_with(&stage) {
return Err(format!("installer executable {exe:?} escapes stage {stage:?}"));
} Type guard
fn staged_executable(stage: &Path, exe: &Path) -> Option<PathBuf> {
fs::canonicalize(exe).ok().filter(|r| r.starts_with(stage))
} Prevention
- Reference installer executables relative to the staged payload
- Update casks rather than hand-editing executable paths
- Only install casks from trusted sources
When it happens
Trigger: A cask's `installer` stanza names an `executable` that, after joining with the stage, cannot be contained by the stage root (e.g. absolute path or one escaping via `..`); detected before checking `is_file`.
Common situations: Mis-authored or tampered cask stanzas pointing at /usr/bin/osascript-like absolute paths; hand-modified local casks; upstream cask changes relocating the installer script.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- brew-cask: app target
- brew-cask: binary target
- brew-cask: generic artifact source is not contained by the…
- brew-cask: invalid generic artifact parent
- brew-cask: refusing generic artifact copy outside Homebrew…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/658cc49bfae1bdfd.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/mod.rs:2382
let relative = appdir.strip_prefix(Path::new("/")).map_err(|_| {
eyre!(
"brew-cask: app directory '{}' must be an absolute path",
appdir.display()
)
})?;
// `allow_current_user` is true because a per-user appdir such as
// `~/Applications` is legitimately owned by the invoking user.
open_trusted_directory(Path::new("/"), relative, true, true)
}
fn run_installer_artifact(
stage: &Path,
installer: &InstallerArtifact,
copied_files: &BTreeSet<PathBuf>,
) -> Result<()> {
let executable = stage.join(&installer.executable);
if staged_relative_path(stage, &executable).is_none() {
bail!(
"brew-cask: refusing installer executable outside trusted installer roots: {}",
executable.display()
);
}
if !executable.is_file() {
bail!(
"brew-cask: installer executable '{}' was not found",
installer.executable
);
}
let executable = file::desymlink_path(&executable);
if !executable.starts_with(file::desymlink_path(stage)) && !copied_files.contains(&executable) {
bail!(
"brew-cask: refusing installer executable outside trusted installer roots: {}",
executable.display()
);
}
file::make_executable(&executable)?;View on GitHub (pinned to 533346cc37)