jdx/mise · error
brew-cask: app target '{target_name}' must not contain '..'
Error message
brew-cask: app target '{target_name}' must not contain '..' What it means
`app_target_path` validates a cask `app` artifact's target path before mise links it into the applications directory. Targets that contain a `/` are parsed as absolute paths, and any `..` component would let the target escape the app-dir containment boundary (symlinks here may be created with elevated privileges). mise rejects such targets with this error as a path-traversal safeguard.
Source
Thrown at src/system/packages/brew/cask/paths.rs:124
return false;
}
}
true
}
pub(super) fn app_target_path(target_name: &str) -> Result<PathBuf> {
let app_dir = target_app_dir()?;
if target_name.contains('\0') {
bail!("brew-cask: app target contains NUL");
}
if target_name.contains('/') {
let target = target_name.replace("$HOMEBREW_PREFIX", &prefix::prefix().to_string_lossy());
let path = PathBuf::from(target);
if path
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!("brew-cask: app target '{target_name}' must not contain '..'");
}
if path.is_absolute() {
let prefix_app_dir = prefix::prefix().join("Applications");
if path.starts_with(&app_dir) || path.starts_with(&prefix_app_dir) {
return Ok(path);
}
// Casks routinely hardcode an absolute `/Applications/Foo.app`
// target. When an override appdir is configured, relocate such a
// target into it (preserving any subdirectories) rather than
// rejecting it. `$HOMEBREW_PREFIX`-anchored targets are handled by
// the check above and are never relocated.
if app_dir != Path::new(DEFAULT_APP_DIR)
&& let Ok(rest) = path.strip_prefix(DEFAULT_APP_DIR)
{
return Ok(app_dir.join(rest));
}
bail!(
"brew-cask: app target '{target_name}' must be under {}",View on GitHub (pinned to afd2eddd3a)
Solutions
- Remove any `..` components from the cask's `app target:` value and use a plain app-bundle name (e.g. `Foo.app`) or an absolute path under the app dir
- If the target should live elsewhere, set an absolute override directory via the brew-cask APP_DIR env var (validated separately) instead of using `..`
- If the cask comes from upstream, verify it is the official definition and update the cask (`mise` refresh / brew update) so the malformed stanza is replaced
- For custom casks, rewrite the target as an absolute path starting with `/Applications/` or `$HOMEBREW_PREFIX/`
Example fix
// before (cask stanza) app target: ['Foo.app', '../Utilities/Bar.app'] // after app target: ['Foo.app', '/Applications/Utilities/Bar.app']
Defensive patterns
Strategy: validation
Validate before calling
fn app_target_ok(target: &str) -> bool {
!target.contains('\0')
&& (!target.contains('/') || {
let p = std::path::Path::new(target.replace("$HOMEBREW_PREFIX", "").as_str());
!p.components().any(|c| matches!(c, std::path::Component::ParentDir))
})
} Type guard
fn is_safe_cask_target(t: &str) -> bool {
!t.contains('\0') && std::path::Path::new(t).components().all(|c| !matches!(c, std::path::Component::ParentDir))
} Try / catch
match cask.install() {
Err(e) if e.to_string().contains("must not contain '..'") => {
eprintln!("fix the cask target: remove '..' components");
}
r => r?,
} Prevention
- Never write `..` in cask `app target:` values
- Prefer bare bundle names and let mise place them in the app dir
- Review third-party/custom cask stanzas for traversal-looking targets before installing
- Test custom casks with a path lint before real installs
When it happens
Trigger: Calling cask install/validation (installed_skip_reason, install_app, app_target_paths, validate_adoptable_apps, appdir_artifact_source) with a cask whose `app target:` string contains `/` and a `..` component, e.g. `['Foo.app', '../../usr/bin']` or a malicious/edited cask stanza.
Common situations: Hand-edited or third-party cask stanzas with relative escape targets; typos in custom cask definitions; attempting to point an app target outside /Applications via `..` instead of an absolute path; copied cask from an untrusted source.
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: binary target '{}' 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/f85a7483778c81ce.
Report an issue: GitHub.