jdx/mise · error
brew-cask: completion target '{}' must not contain '..'
Error message
brew-cask: completion target '{}' must not contain '..' What it means
Before installing a completion artifact, mise resolves the cask's completion target into a concrete path (absolute path used as-is; a name containing '/' joined onto the brew prefix; a bare name placed into the shell's default completion directory) and then rejects any result whose path components include a ParentDir ('..') component. This is a path-traversal guard: a cask must not be able to write completion files outside the intended tree via dot-dot segments.
Source
Thrown at src/system/packages/brew/cask.rs:4426
}
fn completion_target_path(shell: CompletionShell, target_name: &str) -> Result<PathBuf> {
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 {
default_completion_dir(shell).join(completion_filename(shell, &target_name)?)
};
if target
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!(
"brew-cask: completion target '{}' must not contain '..'",
target.display()
);
}
if !target.starts_with(&prefix) {
bail!(
"brew-cask: completion target '{}' must be under {}",
target.display(),
prefix.display()
);
}
Ok(target)
}
fn generated_completion_target_path(shell: CompletionShell, base_name: &str) -> Result<PathBuf> {
match shell {
CompletionShell::Pwsh => {
let name = format!("_{}.ps1", base_name);View on GitHub (pinned to 6f52dcdf99)
Solutions
- Rewrite the completion target to a plain, normalized path with no '..' component — e.g. 'zsh/_tool' or an absolute path genuinely under the brew prefix.
- For bare filenames, drop any directory part entirely and let mise place the file in the shell's default completion directory.
- If you need a specific subdirectory, express it as a forward relative path under the prefix ('share/fish/completions/tool.fish') without traversal.
- If the cask is third-party metadata you cannot edit, report it upstream or skip installing that cask with mise.
Example fix
# before
"completions": { "target": "../../../etc/zshrc" }
# after
"completions": { "target": "zsh/_mytool" } Defensive patterns
Strategy: validation
Validate before calling
# reject traversal before handing metadata to mise
python3 - <<'EOF'
import json,sys
for t in json.load(open(sys.argv[1])).get("completions",[]):
assert ".." not in t["target"].split("/"), t["target"]
EOF Prevention
- Run `realpath -m` on every authored completion target and store the normalized result.
- Never author '..' in targets; prefer bare filenames or single-level subdirectories.
- Sanitize third-party cask JSON through a normalizer before installing.
When it happens
Trigger: A cask completion stanza whose target resolves to something like '../../etc/zshrc' or 'foo/../../bar' — either an absolute target containing '..' (checked as-is) or a relative target with '/' whose join with the prefix contains a ParentDir component. The check at src/system/packages/brew/cask.rs:4426 runs on the resolved target before the additional starts_with(prefix) containment check.
Common situations: Hand-written or machine-generated cask metadata with sloppily built relative paths; a cask edited to 'escape' the completion directory; upstream casks that legitimately used '..' in Homebrew itself (Homebrew allows some of this) but are rejected by mise's stricter containment rules.
Related errors
- brew-cask: completion target '{}' must not contain '..'
- brew-cask: completion target '{}' must be under {}
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/0134d7166c6b74b7.
Report an issue: GitHub.