jdx/mise · error
brew-cask: binary target '{}' must not contain '..'
Error message
brew-cask: binary target '{}' must not contain '..' What it means
After resolving a cask `binary` target (expanding `$HOMEBREW_PREFIX`, joining relative paths to the prefix/bin), `binary_target_path` rejects any resulting path containing `..` components. Like app targets, binary targets become symlinks and `..` would allow escaping the allowed roots (Homebrew prefix, `/usr/local`), so it is blocked as a traversal safeguard.
Source
Thrown at src/system/packages/brew/cask/paths.rs:298
if target_name.contains("$APPDIR") {
bail!("brew-cask: $APPDIR must prefix a binary target");
}
let prefix = prefix::prefix();
let prefix_str = prefix.to_string_lossy();
let target_name = target_name.replace("$HOMEBREW_PREFIX", prefix_str.as_ref());
let path = PathBuf::from(&target_name);
let target = if path.is_absolute() {
path
} else if target_name.contains('/') {
prefix.join(path)
} else {
prefix.join("bin").join(path)
};
if target
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!(
"brew-cask: binary target '{}' must not contain '..'",
target.display()
);
}
let roots = allowed_binary_target_roots();
if !roots.iter().any(|root| target.starts_with(root)) {
bail!(
"brew-cask: binary target '{}' must be under {}",
target.display(),
allowed_binary_target_roots_display(&roots)
);
}
Ok(target)
}
View on GitHub (pinned to afd2eddd3a)
Solutions
- Remove `..` from the target and specify the real path directly (e.g. `/usr/local/bin/tool` instead of `$HOMEBREW_PREFIX/bin/../../usr/local/bin/tool`)
- Use a bare binary name to have it placed in `$HOMEBREW_PREFIX/bin` automatically
- Use an absolute path under the Homebrew prefix or `/usr/local` if the binary must live outside `bin`
- If the cask is upstream, refresh it — a `..` target in an official cask usually indicates a corrupted copy
Example fix
// before (cask stanza)
binary: [['tool', { target: '$HOMEBREW_PREFIX/bin/../../usr/local/bin/tool' }]]
// after
binary: [['tool', { target: '/usr/local/bin/tool' }]] Defensive patterns
Strategy: validation
Validate before calling
fn binary_target_ok(t: &str) -> bool {
let resolved = t.replace("$HOMEBREW_PREFIX", "/opt/homebrew");
let p = std::path::Path::new(&resolved);
!p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Type guard
fn no_parent_components(p: &std::path::Path) -> bool {
!p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Try / catch
match result {
Err(e) if e.to_string().contains("binary target") && e.to_string().contains("must not contain '..'") => {
eprintln!("rewrite the binary target without '..'");
}
r => r?,
} Prevention
- Never use '..' in binary targets; spell out the absolute path
- Use bare names for prefix/bin placement
- When building targets programmatically, join paths instead of concatenating strings
- Review third-party casks for traversal patterns before installing
When it happens
Trigger: Calling `target_path` or `binary_targets_must_stay_under_an_allowed_root` with a cask `binary` target whose resolved path includes `..` — e.g. `binary: '../escape'`, `target: '$HOMEBREW_PREFIX/bin/../../usr/tool'`, or `['tool', { target: '/opt/foo/../bin/bar' }]`.
Common situations: Cask stanza typos with `..`; generated targets that concatenate paths producing `..`; attempting to relocate a binary outside the prefix without an absolute path; malicious/edited third-party casks.
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: invalid {kind} '{value}'
- brew-cask: invalid font target '{}'
- brew-cask: app target '{target_name}' must not contain '..'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/4a5d7b1723b1d4de.
Report an issue: GitHub.