{"record":{"id":"eeb6c9953ecb1ede","repo":"astrid-runtime/astrid","slug":"name-is-not-installed-beside-the-astrid-cli-ref","errorCode":null,"errorMessage":"{name} is not installed beside the Astrid CLI; refusing a PATH provider for a security-sensitive mount","messagePattern":"(.+?) is not installed beside the Astrid CLI; refusing a PATH provider for a security-sensitive mount","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/bootstrap.rs","lineNumber":120,"sourceCode":"         or available in PATH.\"\n    )\n}\n\n/// Locate a security-sensitive companion only in the authenticated install set.\n///\n/// Unlike developer-oriented companion discovery, this deliberately refuses a\n/// `PATH` fallback. A storage provider controls what filesystem the operator\n/// sees, so the executable must be co-installed beside this CLI.\npub(crate) fn find_coinstalled_companion_binary(name: &str) -> Result<std::path::PathBuf> {\n    let executable = std::env::current_exe().context(\"resolve the Astrid CLI executable\")?;\n    let directory = executable\n        .parent()\n        .context(\"the Astrid CLI executable has no installation directory\")?;\n    let candidate = directory.join(format!(\"{name}{}\", std::env::consts::EXE_SUFFIX));\n    if candidate.is_file() {\n        return Ok(candidate);\n    }\n    anyhow::bail!(\n        \"{name} is not installed beside the Astrid CLI; refusing a PATH provider for a security-sensitive mount\"\n    )\n}\n\n/// Run the legacy `astrid build` companion binary, used both by the\n/// hidden top-level `Build` alias and the new `astrid capsule build`.\npub(crate) fn run_build_companion(\n    path: Option<&str>,\n    output: Option<&str>,\n    project_type: Option<&str>,\n    from_mcp_json: Option<&str>,\n) -> Result<ExitCode> {\n    let build_bin = find_companion_binary(\"astrid-build\")?;\n    let mut cmd = std::process::Command::new(build_bin);\n    if let Some(p) = path {\n        cmd.arg(p);\n    }\n    if let Some(o) = output {","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/bootstrap.rs#L102-L138","documentation":"find_coinstalled_companion_binary deliberately does NOT consult PATH. For security-sensitive mounts it only accepts a companion binary that sits in the same directory as the running astrid CLI executable (directory.join(name + EXE_SUFFIX)); anything else could be a hijacked PATH entry. If the sibling file is missing, it bails with this message. This is stricter than find_companion_binary by design.","triggerScenarios":"Calling find_coinstalled_companion_binary when the companion binary is available via PATH but not physically located in the astrid CLI executable's parent directory (or the CLI itself is run from a temp/cargo target path).","commonSituations":"User symlinked only the astrid binary into ~/.local/bin but companions live elsewhere; running astrid via cargo run where companions aren't co-installed; Nix/distro packaging splitting binaries into different directories; a mount-security code path that intentionally rejects PATH resolution.","solutions":["Copy or symlink the companion binary into the same directory as the astrid CLI executable.","Install the complete distribution into one prefix so all binaries are co-located.","Run the astrid CLI from its installed location rather than via cargo run / ad-hoc build output.","If packaging splits binaries, patch the locator to consult your package's libexec directory."],"exampleFix":"# before: astrid in ~/.local/bin, companion elsewhere\n$ which astrid-mount && ls ~/.local/bin/astrid-secure-mount\n~/.local/bin/astrid-mount: ok\nls: ~/.local/bin/astrid-secure-mount: No such file\n\n# after: co-install the companion\n$ ln -s /opt/astrid/bin/astrid-secure-mount ~/.local/bin/astrid-secure-mount","handlingStrategy":"validation","validationCode":"let exe = std::env::current_exe()?;\nlet dir = exe.parent().context(\"no install dir\")?;\nlet name = \"astrid-secure-mount\";\nif !dir.join(format!(\"{name}{}\", std::env::consts::EXE_SUFFIX)).is_file() {\n    eprintln!(\"{name} must sit beside the astrid executable for secure mounts\");\n}","typeGuard":"fn coinstalled(name: &str) -> bool {\n    std::env::current_exe().ok()\n        .and_then(|p| p.parent().map(|d| d.join(format!(\"{name}{}\", std::env::consts::EXE_SUFFIX)).is_file()))\n        .unwrap_or(false)\n}","tryCatchPattern":"match find_coinstalled_companion_binary(\"astrid-secure-mount\") {\n    Ok(p) => { /* use p */ }\n    Err(e) if e.to_string().contains(\"refusing a PATH provider\") => {\n        eprintln!(\"co-install the companion next to the astrid binary\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Co-locate all astrid binaries in one directory at install time.","Do not rely on PATH for security-sensitive companions — that is intentionally unsupported.","Avoid running via `cargo run` for secure-mount flows; run the installed binary.","In packages (deb/nix), keep companions in the same libexec prefix the CLI resolves."],"tags":["cli","security","missing-binary","co-install","path-injection"],"backgroundTag":"command-not-found","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}