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

  1. Fix the cask's installer `executable` to a path relative to the staged payload (e.g. "Foo Installer.app/Contents/MacOS/foo")
  2. Update the cask to the latest version in case the executable location changed upstream
  3. Verify the cask source is trusted; re-fetch rather than hand-editing
  4. 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

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


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)