jdx/mise · error

brew-cask: refusing to stage generic artifact through a path

Error message

brew-cask: refusing to stage generic artifact through a path outside the caskroom: {}

What it means

After resolving the artifact's relative position inside the stage, mise builds the corresponding path under the temporary caskroom and re-verifies containment with path_starts_with_resolved_root. If the constructed caskroom path resolves outside the temporary caskroom (e.g. a component of temporary_caskroom or the relative path is a symlink escaping it), staging is refused so the artifact can never be planted or linked through a location outside mise-controlled space.

Source

Thrown at src/system/packages/brew/cask/mod.rs:1574

            "brew-cask: refusing generic artifact source outside the extraction root: {}",
            source.display()
        );
    }
    let target = generic_artifact_target_path(&artifact.target)?;
    // Not a lexical `strip_prefix`: the lookup resolves symlinks it had to
    // traverse, so a source reached that way can be contained by the stage
    // without sharing its literal prefix — as it is whenever `stage` itself
    // has a symlinked ancestor. `staged_relative_path` retries against the
    // resolved stage, matching the containment check above.
    let relative_source = staged_relative_path(stage, &source).ok_or_else(|| {
        eyre!(
            "brew-cask: generic artifact source is not contained by the extraction root: {}",
            source.display()
        )
    })?;
    let caskroom_source = temporary_caskroom.join(relative_source);
    if !path_starts_with_resolved_root(&caskroom_source, temporary_caskroom) {
        bail!(
            "brew-cask: refusing to stage generic artifact through a path outside the caskroom: {}",
            caskroom_source.display()
        );
    }
    #[cfg(not(unix))]
    if let Some(parent) = target.parent() {
        file::create_dir_all(parent)?;
    }
    let elevated_target = targets.protect_generic(&target)?;
    copy_generic_artifact(&source, &target, elevated_target.as_deref())?;
    if let Some(parent) = caskroom_source.parent() {
        file::create_dir_all(parent)?;
    }
    file::make_symlink(&target, &caskroom_source)?;
    targets.record_installed(target);
    Ok(())
}

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Check the temporary caskroom location for symlinked parents and use a plain directory path
  2. Re-run the install after removing any unexpected symlinks inside the caskroom
  3. Re-download/re-extract the cask to rule out a corrupted payload
  4. Report the issue to mise if your caskroom layout is conventional — this should not trigger on normal setups
Defensive patterns

Strategy: validation

Validate before calling

let caskroom_source = temporary_caskroom.join(&relative_source);
let resolved = dunce::canonicalize(temporary_caskroom)?.join(&relative_source);
if !resolved.starts_with(dunce::canonicalize(&temporary_caskroom)?) {
    return Err(format!("staging path escapes caskroom: {}", caskroom_source.display()));
}

Prevention

When it happens

Trigger: install_generic_artifact computes caskroom_source = temporary_caskroom.join(relative_source), and path_starts_with_resolved_root determines that this joined path resolves outside the temporary caskroom — e.g. due to a symlinked directory at the join point or a relative_source containing traversal-like components that survive normalization.

Common situations: A caskroom parent directory containing symlinks; a compromised or unusual filesystem layout where the temporary caskroom path traverses a link; an artifact source path in the stage that, after staged_relative_path mapping, resolves through a symlink inside the caskroom.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/5a626ed9f618262a. Report an issue: GitHub.