jdx/mise · critical
brew-cask: refusing elevated operation through mutable direc
Error message
brew-cask: refusing elevated operation through mutable directory {} What it means
Before performing elevated (privileged) file operations, mise walks every ancestor of the target path and requires each directory to be trusted: owned by root, not world-writable, and group-writable only when it is exactly the Homebrew prefix (the Intel /usr/local root:admin 0775 convention). If any ancestor is user-owned or more permissive, the elevated operation is refused — writing through a mutable directory with privileges would let anyone on the machine plant or swap the file being installed.
Source
Thrown at src/system/packages/brew/cask.rs:1884
target
.file_name()
.ok_or_else(|| eyre!("brew-cask: generic artifact target has no filename"))?,
))
}
#[cfg(unix)]
fn validate_strict_elevated_ancestors(path: &Path) -> Result<()> {
use std::os::unix::fs::MetadataExt;
let stable_prefix = file::desymlink_path(&prefix::prefix());
for directory in path.ancestors() {
let metadata = directory.symlink_metadata()?;
if !strict_elevated_directory_is_trusted(
directory,
&stable_prefix,
metadata.uid(),
metadata.mode(),
) {
bail!(
"brew-cask: refusing elevated operation through mutable directory {}",
directory.display()
);
}
}
Ok(())
}
#[cfg(unix)]
fn strict_elevated_directory_is_trusted(
directory: &Path,
stable_prefix: &Path,
uid: u32,
mode: u32,
) -> bool {
uid == 0
&& mode & 0o002 == 0
// Intel Homebrew conventionally uses root:admin 0775 for /usr/local.View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Fix ownership/permissions of the offending directory (named in the error): sudo chown root:admin <dir> && sudo chmod 755 <dir>
- Group-writability is only tolerated on the Homebrew prefix itself; tighten subdirectories
- Avoid casks whose artifact targets live in user-writable paths — report them to the tap
Defensive patterns
Strategy: validation
Validate before calling
use std::os::unix::fs::MetadataExt;
fn elevated_path_trusted(path: &Path, prefix: &Path) -> Result<bool> {
for dir in path.ancestors() {
let m = dir.symlink_metadata()?;
let group_ok = m.mode() & 0o020 == 0 || dir == prefix;
if !(m.uid() == 0 && m.mode() & 0o002 == 0 && group_ok) {
return Ok(false);
}
}
Ok(true)
}
// call before requesting any elevated cask install Try / catch
Catch 'refusing elevated operation through mutable directory' and fix the named directory's ownership/permissions; never catch-and-continue with a different, less-checked path.
Prevention
- Keep artifact target directories root-owned and 755 (group-writable only on the Homebrew prefix itself)
- Avoid casks that install into user-writable paths with elevation
- Audit /usr/local subdirectories for stray admin-writable modes on Intel Macs
When it happens
Trigger: A cask artifact whose target lives under a user-writable directory (e.g. /Users/<you>/bin, /tmp/...) while mise escalates to install it, or a target under /usr/local where a non-prefix subdirectory is group-writable.
Common situations: Niche casks with artifact targets inside $HOME; systems where directories under /usr/local were chmod'ed to 0775+ by admin tooling; mixed Homebrew prefix conventions on Intel Macs.
Related errors
- brew-cask: temporary artifact directory is not private
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
- brew-cask: refusing to stage generic artifact through a path
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/0646ed89044d1755.
Report an issue: GitHub.