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
- Inspect the cask definition's artifact/payload paths and remove any '..' segments or absolute paths so the staged path stays inside the caskroom
- Verify the cask source/registry is trusted — this message is often a deliberate safety rejection of a malformed or hostile cask
- Check for pre-existing symlinks in the caskroom that redirect the target path, and remove/relink them
- 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
- Keep cask artifact paths relative and free of '..' segments
- Only install casks from trusted sources
- Audit caskroom for symlinks before staging
- Validate the cask stanza's paths in CI before deploying it
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
- brew-cask: refusing generic artifact source outside the…
- app Info.plist must be a regular file
- brew-cask: invalid app source
- brew-cask: invalid structured flight path
- brew-cask: ' ' must stay below Applications
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)