jdx/mise · error
brew-cask: refusing generic artifact source outside the extr
Error message
brew-cask: refusing generic artifact source outside the extraction root: {} What it means
When installing a cask's generic artifact, mise locates the source file matching artifact.source inside the extraction (stage) root, then verifies with path_starts_with_resolved_root that the found path is actually resolved-contained within the stage. If the resolved location falls outside the extraction root (e.g. the lookup had to traverse a symlink pointing out of the tree), installation is refused to keep a cask from exfiltrating or overwriting files outside its own payload.
Source
Thrown at src/system/packages/brew/cask/mod.rs:1555
let Ok(relative) = source.strip_prefix(temporary_caskroom) else {
continue;
};
file::remove_file(&target)?;
create_flight_symlink(&final_caskroom.join(relative), &target, FlightSudo::Never)?;
}
Ok(())
}
fn install_generic_artifact(
stage: &Path,
temporary_caskroom: &Path,
artifact: &GenericArtifact,
targets: &mut FlightTargetTransaction,
) -> Result<()> {
let source = find_artifact_matching(stage, &artifact.source, |_| true)
.ok_or_else(|| eyre!("brew-cask: artifact '{}' was not found", artifact.source))?;
if !path_starts_with_resolved_root(&source, stage) {
bail!(
"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) {View on GitHub (pinned to afd2eddd3a)
Solutions
- Inspect the extracted stage for out-of-tree symlinks and remove/fix them before reinstalling
- Re-download/re-extract the cask to rule out corruption or tampering
- Ensure mise's caskroom/stage paths are not themselves behind unexpected symlinks
- Report the cask upstream if the artifact genuinely lives outside the payload
Defensive patterns
Strategy: validation
Validate before calling
// verify the artifact source stays inside the stage after resolution
let resolved = dunce::canonicalize(stage.join(&artifact.source))?;
if !resolved.starts_with(dunce::canonicalize(stage)?) {
return Err(format!("artifact source resolves outside stage: {}", resolved.display()));
} Prevention
- Keep cask payload symlinks pointing only within the payload tree
- Avoid declaring artifact.source patterns that can match symlinked paths
- Extract the stage on a filesystem without symlinked intermediates
- Verify cask integrity (checksum) before extraction
When it happens
Trigger: Calling install_generic_artifact where find_artifact_matching resolves the cask's declared `source` glob/pattern to a path whose fully-resolved location is not under the stage directory. Typically caused by symlinked directories inside the extracted payload pointing out of the tree.
Common situations: A maliciously or accidentally crafted cask whose payload contains symlinks out of the stage; the artifact source pattern matching a symlinked path that resolves elsewhere; a stage directory placed under a symlinked path interacting with lookup resolution.
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
- brew-cask: refusing to stage generic artifact through a path
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: invalid {kind} '{value}'
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/82025f9ffec2a3f8.
Report an issue: GitHub.