{"record":{"id":"4a5d7b1723b1d4de","repo":"jdx/mise","slug":"brew-cask-binary-target-must-not-contain-4a5d7b","errorCode":null,"errorMessage":"brew-cask: binary target '{}' must not contain '..'","messagePattern":"brew-cask: binary target '(.+?)' must not contain '\\.\\.'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/paths.rs","lineNumber":298,"sourceCode":"    if target_name.contains(\"$APPDIR\") {\n        bail!(\"brew-cask: $APPDIR must prefix a binary target\");\n    }\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        prefix.join(\"bin\").join(path)\n    };\n    if target\n        .components()\n        .any(|component| matches!(component, Component::ParentDir))\n    {\n        bail!(\n            \"brew-cask: binary target '{}' must not contain '..'\",\n            target.display()\n        );\n    }\n    let roots = allowed_binary_target_roots();\n    if !roots.iter().any(|root| target.starts_with(root)) {\n        bail!(\n            \"brew-cask: binary target '{}' must be under {}\",\n            target.display(),\n            allowed_binary_target_roots_display(&roots)\n        );\n    }\n    Ok(target)\n}\n","sourceCodeStart":280,"sourceCodeEnd":313,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/paths.rs#L280-L313","documentation":"This error is thrown by `binary_target_path` in src/system/packages/brew/cask/paths.rs when the fully resolved binary target path contains a `..` (ParentDir) component. The library rejects parent-directory traversal so a cask binary cannot be linked outside the sanctioned Homebrew/appdir trees; this is a path-traversal guard applied after `$HOMEBREW_PREFIX` substitution and prefix-relative resolution.","triggerScenarios":"Calling `binary_target_path(target_name, appdir)` where, after replacing `$HOMEBREW_PREFIX` and resolving bare names to `<prefix>/bin/<name>`, the resulting path contains a `..` component — e.g. `../evil`, `$HOMEBREW_PREFIX/bin/../../tmp/x`, or `$APPDIR/../elsewhere` (that last one is caught earlier by `reject_appdir_escape` but the same rule applies to prefix targets).","commonSituations":"A malicious or buggy cask formula uses relative escapes; a user hand-edits a binary stanza with `..`; generated target strings from scripts accidentally embed `..`; migration of a formula from another manager kept relative links.","solutions":["Rewrite the binary target as an absolute path or one relative to the Homebrew prefix without any `..` components","Use `$HOMEBREW_PREFIX` substitution instead of climbing with `..` to reach another tree","Verify the cask formula is from a trusted source; a `..` in an official formula is suspicious","If the intended binary is genuinely outside the allowed roots, link it manually instead of via this path"],"exampleFix":"// before\nbinary_target_path(\"$HOMEBREW_PREFIX/bin/../libexec/tool\", &appdir)\n// error: binary target must not contain '..'\n\n// after\nbinary_target_path(\"$HOMEBREW_PREFIX/libexec/tool\", &appdir)","handlingStrategy":"validation","validationCode":"fn target_has_parent_dir(target: &std::path::Path) -> bool {\n    target.components().any(|c| matches!(c, std::path::Component::ParentDir))\n}","typeGuard":"fn safe_target(t: &str) -> Option<&str> {\n    if target_has_parent_dir(std::path::Path::new(t)) { None } else { Some(t) }\n}","tryCatchPattern":"match binary_target_path(target_name, &appdir) {\n    Ok(path) => use(path),\n    Err(e) if e.to_string().contains(\"must not contain '..'\") => rewrite_without_traversal(target_name),\n    Err(e) => return Err(e),\n}","preventionTips":["Never include `..` in binary target strings; resolve to absolute prefix paths instead","Use `$HOMEBREW_PREFIX` substitution to reach other Homebrew trees","Audit third-party cask stanzas for traversal components before use"],"tags":["path-validation","path-traversal","brew-cask","security"],"backgroundTag":"path-traversal-blocked","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}