jdx/mise · error
brew-cask: binary target
Error message
brew-cask: binary target '{}' must not contain '..' What it means
This error is thrown by `binary_target_path` in src/system/packages/brew/cask/paths.rs when the fully resolved binary target path contains a `..` (ParentDir) component. The library rejects parent-directory traversal so a cask binary cannot be linked outside the sanctioned Homebrew/appdir trees; this is a path-traversal guard applied after `$HOMEBREW_PREFIX` substitution and prefix-relative resolution.
Solutions
- Rewrite the binary target as an absolute path or one relative to the Homebrew prefix without any `..` components
- Use `$HOMEBREW_PREFIX` substitution instead of climbing with `..` to reach another tree
- Verify the cask formula is from a trusted source; a `..` in an official formula is suspicious
- If the intended binary is genuinely outside the allowed roots, link it manually instead of via this path
Example fix
// before
binary_target_path("$HOMEBREW_PREFIX/bin/../libexec/tool", &appdir)
// error: binary target must not contain '..'
// after
binary_target_path("$HOMEBREW_PREFIX/libexec/tool", &appdir) Defensive patterns
Strategy: validation
Validate before calling
fn target_has_parent_dir(target: &std::path::Path) -> bool {
target.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Type guard
fn safe_target(t: &str) -> Option<&str> {
if target_has_parent_dir(std::path::Path::new(t)) { None } else { Some(t) }
} Try / catch
match binary_target_path(target_name, &appdir) {
Ok(path) => use(path),
Err(e) if e.to_string().contains("must not contain '..'") => rewrite_without_traversal(target_name),
Err(e) => return Err(e),
} Prevention
- Never include `..` in binary target strings; resolve to absolute prefix paths instead
- Use `$HOMEBREW_PREFIX` substitution to reach other Homebrew trees
- Audit third-party cask stanzas for traversal components before use
When it happens
Trigger: Calling `binary_target_path(target_name, appdir)` where, after replacing `$HOMEBREW_PREFIX` and resolving bare names to `<prefix>/bin/<name>`, the resulting path contains a `..` component — e.g. `../evil`, `$HOMEBREW_PREFIX/bin/../../tmp/x`, or `$APPDIR/../elsewhere` (that last one is caught earlier by `reject_appdir_escape` but the same rule applies to prefix targets).
Common situations: A malicious or buggy cask formula uses relative escapes; a user hand-edits a binary stanza with `..`; generated target strings from scripts accidentally embed `..`; migration of a formula from another manager kept relative links.
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: generic artifact source is not contained by the…
- brew-cask: invalid generic artifact parent
- brew-cask: refusing generic artifact copy outside Homebrew…
- brew-cask: refusing installer executable outside trusted…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/4a5d7b1723b1d4de.
Report an issue: GitHub.
Appendix: 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 533346cc37)