jdx/mise · error

brew-cask: refusing to stage cask payload through a path…

Error message

brew-cask: refusing to stage cask payload through a path outside the caskroom: {}

What it means

This error is thrown by the brew-cask staging code when the computed installation target path (caskroom + staged relative path) resolves outside the caskroom root. The library refuses to write cask payloads through paths that escape the caskroom, because such a path could overwrite arbitrary files via symlinks or '..' components in the cask payload layout.

Solutions

  1. Inspect the cask definition's artifact/payload paths and remove any '..' segments or absolute paths so the staged path stays inside the caskroom
  2. Verify the cask source/registry is trusted — this message is often a deliberate safety rejection of a malformed or hostile cask
  3. Check for pre-existing symlinks in the caskroom that redirect the target path, and remove/relink them
  4. Update the cask to a fixed version or report the broken cask stanza upstream

Example fix

// before: payload path escapes caskroom
let relative = Path::new("../../Library/staged.bin");
// after: keep the staged path inside the caskroom
let relative = Path::new("Casks/staged.bin");
Defensive patterns

Strategy: validation

Validate before calling

fn is_inside_caskroom(target: &Path, caskroom: &Path) -> bool {
    let resolved = target.canonicalize().unwrap_or_else(|_| target.to_path_buf());
    resolved.starts_with(caskroom)
}
// call before staging: assert!(is_inside_caskroom(&caskroom.join(&relative), &caskroom))

Prevention

When it happens

Trigger: Calling the cask staging flow for a cask whose staged payload path, once joined to the caskroom and path-starts-with-resolved-root checked, resolves to a location outside the caskroom directory — e.g. a payload relative path containing '..' or pointing at an absolute/symlinked location.

Common situations: A cask definition (custom or from a registry) declares artifact paths with '../' segments or absolute paths; a malicious or corrupted cask stanza tries to write outside the install prefix; a symlink inside the caskroom points elsewhere before staging.

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/77abecf29da5c6e3. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/brew/cask/mod.rs:3327

        .iter()
        .filter_map(|app| find_app(stage, &app.source))
        .map(|source| file::desymlink_path(&source))
        .collect();
    for entry in std::fs::read_dir(stage)? {
        let source = entry?.path();
        if !path_starts_with_resolved_root(&source, stage) {
            continue;
        }
        let resolved = file::desymlink_path(&source);
        if app_sources.contains(&resolved) {
            continue;
        }
        let Some(relative) = staged_relative_path(stage, &source) else {
            continue;
        };
        let target = caskroom.join(&relative);
        if !path_starts_with_resolved_root(&target, caskroom) {
            bail!(
                "brew-cask: refusing to stage cask payload through a path outside the caskroom: {}",
                target.display()
            );
        }
        if target.symlink_metadata().is_ok() {
            continue;
        }
        if let Some(parent) = target.parent() {
            file::create_dir_all(parent)?;
        }
        if source.is_dir() {
            file::copy_dir_all_preserve_symlinks(&source, &target)?;
        } else {
            file::copy(&source, &target)?;
        }
    }
    Ok(())
}

View on GitHub (pinned to 533346cc37)