{"record":{"id":"019fceebf5881236","repo":"jdx/mise","slug":"brew-cask-refusing-elevated-operation-because-tar","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.rs","lineNumber":1912,"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#[cfg(unix)]\nfn copy_cask_artifact_at<Fd: std::os::fd::AsFd>(\n    from: &Path,\n    parent: Fd,\n    name: &std::ffi::OsStr,\n) -> Result<()> {\n    use std::os::unix::fs::PermissionsExt;\n\n    let metadata = from.symlink_metadata()?;\n    let mode = nix::sys::stat::Mode::from_bits_truncate(\n        metadata.permissions().mode() as nix::libc::mode_t","sourceCodeStart":1894,"sourceCodeEnd":1930,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/packages/brew/cask.rs#L1894-L1930","documentation":"Elevated installs are only allowed to create targets, never overwrite: right before the privileged rename/copy, mise stats the target (ensure_target_absent). If anything — file, symlink, or directory — now exists where the plan assumed absence, the operation is refused. This closes the TOCTOU window where a swapped-in symlink at the target could redirect a privileged write.","triggerScenarios":"Something creates the target path between mise's earlier planning and the elevated step: a concurrent installer (brew, another mise run, a package installer), a login script, or an attacker racing the install.","commonSituations":"Parallel bootstrap scripts installing the same binary; re-running mise while a previous run's elevated step is still finishing; dotfiles daemons that continuously recreate symlinks.","solutions":["Identify what created the target (path is in the error); if it came from a concurrent install, let it finish and re-run mise — it will detect the existing version","If the target is stale, remove it deliberately (verify it is not a symlink someone else planted) and retry","Serialize installers so two privileged writers never race the same path"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Best-effort pre-check (still racy — the library re-checks atomically):\nfn target_absent(target: &Path) -> bool {\n    matches!(target.symlink_metadata(), Err(e) if e.kind() == std::io::ErrorKind::NotFound)\n}","typeGuard":null,"tryCatchPattern":"Catch 'refusing elevated operation because target appeared'; verify the appeared target's provenance (lstat it, check owner and symlink-ness), remove it if it is your own stale artifact, then retry. Never blindly unlink — the whole point of the guard is that something raced you.","preventionTips":["Serialize privileged installers so two writers never target the same path","Don't run mise bootstrap while login scripts recreate symlinks in target directories"],"tags":["homebrew","cask","toctou","race-condition","security","mise"],"backgroundTag":"target-file-already-exists","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}