{"record":{"id":"451ade49026e26ef","repo":"jdx/mise","slug":"brew-cask-completion-target-must-not-contain-451ade","errorCode":null,"errorMessage":"brew-cask: completion target '{}' must not contain '..'","messagePattern":"brew-cask: completion target '(.+?)' must not contain '\\.\\.'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/mod.rs","lineNumber":2955,"sourceCode":"}\n\nfn completion_target_path(shell: CompletionShell, target_name: &str) -> Result<PathBuf> {\n    let prefix = prefix::prefix();\n    let prefix_str = prefix.to_string_lossy();\n    let target_name = target_name.replace(\"$HOMEBREW_PREFIX\", prefix_str.as_ref());\n    let path = PathBuf::from(&target_name);\n    let target = if path.is_absolute() {\n        path\n    } else if target_name.contains('/') {\n        prefix.join(path)\n    } else {\n        default_completion_dir(shell).join(completion_filename(shell, &target_name)?)\n    };\n    if target\n        .components()\n        .any(|component| matches!(component, Component::ParentDir))\n    {\n        bail!(\n            \"brew-cask: completion target '{}' must not contain '..'\",\n            target.display()\n        );\n    }\n    if !target.starts_with(&prefix) {\n        bail!(\n            \"brew-cask: completion target '{}' must be under {}\",\n            target.display(),\n            prefix.display()\n        );\n    }\n    Ok(target)\n}\n\nfn generated_completion_target_path(shell: CompletionShell, base_name: &str) -> Result<PathBuf> {\n    match shell {\n        CompletionShell::Pwsh => {\n            let name = format!(\"_{}.ps1\", base_name);","sourceCodeStart":2937,"sourceCodeEnd":2973,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/mod.rs#L2937-L2973","documentation":"mise validates that a cask's declared completion target path, after shell-specific directory resolution, stays inside the managed completions tree. If any path component is `..`, the target could escape that tree, so mise rejects it before any filesystem writes — a path traversal guard on completion stanzas.","triggerScenarios":"`target.components().any(|c| matches!(c, Component::ParentDir))` is true while computing the final completion destination (e.g. from a cask stanza like `\"../../etc/foo\"`).","commonSituations":"A hand-written or third-party cask declares a completion path containing `..`; templating in a cask expands to a path with parent references; a typo like `\"..\"` in a relative completion path.","solutions":["Rewrite the completion target in the cask definition as a clean relative path without `..`","Use the shell's default completion directory implicitly instead of overriding with a parent-relative path","Treat this error as a security signal if the cask came from an untrusted source — do not bypass it"],"exampleFix":"// before (cask stanza)\ncompletion \"../../usr/local/share/zsh/site-functions/_x\"\n// after\ncompletion \"_x\"  # placed under the managed completion dir","handlingStrategy":"validation","validationCode":"let t = std::path::Path::new(target);\nassert!(!t.components().any(|c| matches!(c, std::path::Component::ParentDir)), \"completion target must not contain '..'\");","typeGuard":"fn has_no_parent_components(p: &std::path::Path) -> bool {\n  !p.components().any(|c| matches!(c, std::path::Component::ParentDir))\n}","tryCatchPattern":"if let Err(e) = result {\n  if e.contains(\"must not contain '..'\") {\n    eprintln!(\"completion target rejected as traversal; rewrite it as a relative path under the completion dir\");\n  }\n}","preventionTips":["Write completion stanzas as bare relative paths/filenames","Never use parent references in cask path fields","Treat rejection of third-party casks as a security signal"],"tags":["path-traversal","security","brew-cask","completions"],"backgroundTag":"path-traversal-blocked","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}