jdx/mise · error
brew-cask: {APP_DIR_ENV} '{}' must not contain '..'
Error message
brew-cask: {APP_DIR_ENV} '{}' must not contain '..' What it means
The brew-cask app-dir override env var must not contain `..` components; `target_app_dir` uses the value as a symlink-free containment boundary for privileged operations, and a `..` component could redirect installs outside the intended directory. The value is rejected before any resolution occurs.
Source
Thrown at src/system/packages/brew/cask/paths.rs:177
pub(super) fn target_app_dir() -> Result<PathBuf> {
let Ok(dir) = crate::env::var(APP_DIR_ENV) else {
return Ok(PathBuf::from(DEFAULT_APP_DIR));
};
if dir.is_empty() {
return Ok(PathBuf::from(DEFAULT_APP_DIR));
}
let dir = PathBuf::from(dir);
if !dir.is_absolute() {
bail!(
"brew-cask: {APP_DIR_ENV} '{}' must be an absolute path",
dir.display()
);
}
if dir
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!(
"brew-cask: {APP_DIR_ENV} '{}' must not contain '..'",
dir.display()
);
}
// Resolve the override to a real absolute path: canonicalize its longest
// existing prefix and re-append the components that do not exist yet. This
// makes the appdir a symlink-free containment boundary — privileged cask
// mutations then operate on resolved paths and cannot be redirected through
// a symlinked component — and it collapses every spelling of the filesystem
// root (`/`, `//`, `/.`, a symlink to `/`, ...) to `/` so they can all be
// rejected together.
let resolved = resolve_appdir(&dir);
if !resolved
.components()
.any(|component| matches!(component, Component::Normal(_)))
{
bail!(
"brew-cask: {APP_DIR_ENV} '{}' must not resolve to the filesystem root",View on GitHub (pinned to afd2eddd3a)
Solutions
- Rewrite the env var value without `..`, using the real absolute path (e.g. `/Users/other/Apps` instead of `/Users/me/../other/Apps`)
- Canonicalize the value when setting it: `export MISE_BREW_CASK_OPT_APPDIR="$(cd /path/../real && pwd)"` in a context where it resolves as intended
- Fix the build/script logic that composes the path so it never emits `..`
- Unset the var to use the default app dir
Example fix
// before (shell) export MISE_BREW_CASK_OPT_APPDIR=/Users/me/../shared/Apps // after export MISE_BREW_CASK_OPT_APPDIR=/Users/shared/Apps
Defensive patterns
Strategy: validation
Validate before calling
fn appdir_env_ok(v: &str) -> bool {
let p = std::path::Path::new(v);
p.is_absolute() && !p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Type guard
fn has_no_parent_dirs(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("must not contain '..'") && e.to_string().contains("APPDIR") => {
eprintln!("rewrite the override without '..' components");
}
r => r?,
} Prevention
- Compose the override from literal absolute segments, never by appending '..'
- Canonicalize paths in scripts before exporting them
- Treat '..' in config values as a smell — replace with the resolved path
- Unset the var rather than hacking around a bad value
When it happens
Trigger: Exporting APP_DIR_ENV to a path containing `..` (e.g. `MISE_BREW_CASK_OPT_APPDIR=/Users/me/../etc/Apps`) and then running cask install/validation that calls `target_app_dir` (directly or through `app_target_path`, `cask_appdir`, `target_path`, `allowed_appdir_roots`).
Common situations: Path assembled by string concatenation from variables that produce `..`; users trying to normalize a path by hand; scripts that append `../..` to 'go up' a tree.
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: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
- brew-cask: refusing to stage generic artifact through a path
- brew-cask: completion target '{}' must not contain '..'
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/b0de1d2ca0e0ff85.
Report an issue: GitHub.