{"record":{"id":"fbb3facb3a8f9cee","repo":"jdx/mise","slug":"brew-cask-binary-target-must-be-under-fbb3fa","errorCode":null,"errorMessage":"brew-cask: binary target '{}' must be under {}","messagePattern":"brew-cask: binary target '(.+?)' must be under (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/paths.rs","lineNumber":305,"sourceCode":"    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":287,"sourceCodeEnd":313,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/paths.rs#L287-L313","documentation":"binary_target_path validates that a cask's binary symlink/stanza target resolves under one of the allowed root directories (e.g. prefix/bin, /usr/local/bin, /opt/homebrew/bin). If the target path is not under any allowed root (and is not rejected earlier for containing '..'), mise refuses the operation rather than writing a binary outside managed locations. This guards against casks that declare unusual binary destinations.","triggerScenarios":"Calling binary_target_path (via target_path or binary_targets_must_be_under_an_allowed_root) with a cask binary stanza target whose resolved path does not start with any root returned by allowed_binary_target_roots() — e.g. a cask installs its binary into /Applications or a custom prefix subdirectory.","commonSituations":"Installing an unusual third-party cask whose binary stanza points outside standard Homebrew bin directories; Homebrew prefix changes (Intel /usr/local vs Apple Silicon /opt/homebrew) leaving roots misaligned; hand-edited cask definitions.","solutions":["Inspect the cask's binary stanza and confirm the target directory is a standard Homebrew bin path","Run `brew reinstall --cask <token>` so Homebrew itself places the binary correctly, then retry","If the cask is wrong, fix or update the cask definition (brew tap-homebrew / cask edit) so targets fall under allowed roots","Verify your Homebrew prefix matches allowed_binary_target_roots() expectations for your platform"],"exampleFix":"// before: cask stanza pointing outside allowed roots\nbinary \"#{appdir}/MyTool.app/Contents/MacOS/mytool\"\n// after: target under the Homebrew prefix bin root, e.g.\nbinary \"#{staged_path}/mytool\"","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn is_under_allowed_root(target: &Path, roots: &[&Path]) -> bool {\n    !target.components().any(|c| c.as_os_str() == \"..\")\n        && roots.iter().any(|root| target.starts_with(root))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep cask binary stanzas pointing at standard Homebrew prefix bin directories","Keep your Homebrew prefix standard for your platform (/opt/homebrew on Apple Silicon, /usr/local on Intel)","Update cask definitions rather than hand-editing targets outside allowed roots"],"tags":["path-validation","homebrew","cask","security"],"backgroundTag":"invalid-argument-value","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"}