jdx/mise · error
brew-cask: {kind} '{name}' must stay below Applications
Error message
brew-cask: {kind} '{name}' must stay below Applications What it means
reject_appdir_escape validates that app/artifact target paths stay strictly beneath the Applications directory: the relative path must be non-empty and composed only of normal components. Empty paths or paths containing '..', '.', root, or prefix components are rejected.
Source
Thrown at src/system/packages/brew/cask/mod.rs:3365
let relative = source.strip_prefix(final_caskroom).ok()?;
if relative
.components()
.any(|component| matches!(component, Component::ParentDir))
{
return None;
}
Some(root.join(relative))
}
/// Rejects an empty relative path and any component that could climb out of
/// `$APPDIR` (`..`, a root, a prefix).
fn reject_appdir_escape(relative: &Path, kind: &str, name: &str) -> Result<()> {
if relative.components().next().is_none()
|| relative
.components()
.any(|component| !matches!(component, Component::Normal(_)))
{
bail!("brew-cask: {kind} '{name}' must stay below Applications");
}
Ok(())
}
fn resolve_symlink_target(link: &Path, target: PathBuf) -> PathBuf {
if target.is_absolute() {
target
} else {
link.parent()
.map(|parent| parent.join(&target))
.unwrap_or(target)
}
}
fn durable_internal_symlink_source(stage: &Path, source: &Path, link: &Path) -> Option<PathBuf> {
if !source.is_absolute()
|| staged_relative_path(stage, source).is_none()
|| staged_relative_path(stage, link).is_none()View on GitHub (pinned to afd2eddd3a)
Solutions
- Set the app target to a simple relative name like `Foo.app` that lives directly under Applications
- Remove `..`, absolute, or special path components from the target
- Check the upstream Homebrew cask for the canonical target name
Example fix
// before target = "../Utilities/Foo.app" // after target = "Foo.app"
Defensive patterns
Strategy: validation
Validate before calling
let rel = Path::new(target_name);
let ok = !target_name.is_empty()
&& rel.is_relative()
&& rel.components().all(|c| matches!(c, Component::Normal(_)));
if !ok {
return Err("app target must be a simple path under Applications");
} Prevention
- Keep app targets as plain 'Name.app' relative names
- Reject absolute paths and '..' in artifact targets during parsing
When it happens
Trigger: Installing a cask app (or similar kind) whose resolved target name is empty, absolute, or contains non-Normal components such as `..`, `/`, or a drive/root prefix.
Common situations: A cask stanza targeting a location outside /Applications (e.g. `../Utilities/Foo.app` or an absolute `/Library/Foo.app`), or a target template that expanded to an empty string.
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 copy outside Homebrew p
- brew-cask: {APP_DIR_ENV} '{}' must not resolve to the filesy
- brew-cask: invalid {kind} '{value}'
- brew-cask:{}: cask metadata has no sha256
- brew-cask: staged symlink path escaped extraction root: {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/995f7f5ffe1c86e0.
Report an issue: GitHub.