{"record":{"id":"69fd819feea68b8d","repo":"jdx/mise","slug":"brew-cask-refusing-elevated-operation-because-tar-69fd81","errorCode":null,"errorMessage":"brew-cask: refusing elevated operation because target appeared: {}","messagePattern":"brew-cask: refusing elevated operation because target appeared: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/mod.rs","lineNumber":1758,"sourceCode":"fn strict_elevated_directory_is_trusted(\n    directory: &Path,\n    stable_prefix: &Path,\n    uid: u32,\n    mode: u32,\n) -> bool {\n    uid == 0\n        && mode & 0o002 == 0\n        // Intel Homebrew conventionally uses root:admin 0775 for /usr/local.\n        // Permit that exact prefix, but require every descendant and every\n        // other ancestor used by the elevated operation to be non-writable.\n        && (mode & 0o020 == 0 || directory == stable_prefix)\n}\n\n#[cfg(unix)]\nfn ensure_target_absent(target: &Path) -> Result<()> {\n    match target.symlink_metadata() {\n        Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(()),\n        Ok(_) => bail!(\n            \"brew-cask: refusing elevated operation because target appeared: {}\",\n            target.display()\n        ),\n        Err(err) => Err(err.into()),\n    }\n}\n\n/// Opens a directory relative to `parent`, never following symlinks.\n#[cfg(unix)]\nfn open_dir_nofollow_at<Fd: std::os::fd::AsFd, P: nix::NixPath + ?Sized>(\n    parent: Fd,\n    name: &P,\n) -> Result<std::os::fd::OwnedFd> {\n    Ok(nix::fcntl::openat(\n        parent,\n        name,\n        nix::fcntl::OFlag::O_RDONLY\n            | nix::fcntl::OFlag::O_DIRECTORY","sourceCodeStart":1740,"sourceCodeEnd":1776,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/mod.rs#L1740-L1776","documentation":"This error is a TOCTOU (time-of-check-time-of-use) safety guard in `ensure_target_absent`. Before performing an elevated operation against a path, the function verifies the path does not exist via `symlink_metadata`; if a file, directory, or symlink has appeared at the target between the initial check and the elevated action, the operation is aborted rather than clobbering an object an attacker may have planted. It protects against symlink-swap races where a malicious local process creates a link at the destination path mid-operation.","triggerScenarios":"Calling a privileged brew-cask operation that resolves through `ensure_target_absent` when `target.symlink_metadata()` returns `Ok` — i.e. the target path (or a symlink at that path) exists at the moment of the re-check, typically because another process created it concurrently or a stale file from a previous failed run is present.","commonSituations":"A previous interrupted install left a file or dangling symlink at the cask artifact destination; a parallel brew/cask process racing on the same path; a malicious or accidental symlink planted at the destination; Nix/tmpfs state carried over between runs.","solutions":["Inspect the path named in the message (`target.display()`); if it is a leftover from an earlier failed run and nothing depends on it, remove the file/symlink and retry.","Verify no other brew or cask process is running concurrently against the same prefix; serialize operations.","If the target is legitimately expected to exist, this operation is intentionally refused — restructure the call so the path is clear, or use a non-elevated path that handles existing targets.","If the path reappears on every attempt, check for background jobs (launchd/cron, other package managers) recreating it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn target_is_clear(target: &Path) -> bool {\n    matches!(target.symlink_metadata(), Err(e) if e.kind() == std::io::ErrorKind::NotFound)\n}\n// before calling the elevated operation:\nif !target_is_clear(&target) { eprintln!(\"target exists: {}\", target.display()); }\n","typeGuard":"fn path_is_absent(p: &Path) -> bool {\n    p.symlink_metadata().map_err(|e| e.kind() == std::io::ErrorKind::NotFound).unwrap_or(false)\n}\n","tryCatchPattern":null,"preventionTips":["Clean up leftover files/symlinks at artifact destinations after failed installs before retrying.","Never run concurrent brew/cask operations against the same prefix.","Ensure no background jobs write into the Homebrew prefix."],"tags":["security","race-condition","symlink","toctou"],"backgroundTag":"internal-invariant-violation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}