jdx/mise · error
brew-cask: invalid generic artifact parent
Error message
brew-cask: invalid generic artifact parent
What it means
While resolving (and optionally creating) the parent directories of a generic artifact target via fd-based `openat` traversal, mise requires every path component to be a plain `Normal` component. Components like `..`, `.`, or a root/empty component abort the traversal, since relative paths with up-level components could escape the resolved root.
Solutions
- Fix the cask's `target` to a clean relative path without `..` or `.` components
- Normalize the target with a path library before installing if you generate the stanza programmatically
- Update the cask to a version with a corrected target
- Report the cask upstream if it ships an invalid target
Example fix
// before // target: "../shared/Foo.app" // after // target: "shared/Foo.app"
Defensive patterns
Strategy: validation
Validate before calling
let rel = Path::new(&cask_target);
for c in rel.components() {
if !matches!(c, std::path::Component::Normal(_)) {
return Err(format!("target contains non-normal component: {c:?}"));
}
} Type guard
fn is_clean_relative(p: &Path) -> bool {
p.is_relative() && p.components().all(|c| matches!(c, std::path::Component::Normal(_)))
} Prevention
- Never use `..` or `.` in artifact targets
- Normalize generated paths before writing cask stanzas
- Validate targets in CI when authoring casks
When it happens
Trigger: A cask generic artifact `target` normalizes to a relative path containing `..`, `.`, or non-normal components when walking from the resolved root in `open_trusted_operation_parent`-style traversal.
Common situations: Hand-edited cask stanzas using targets like "../share/foo" or "/abs/path" where a relative path is expected; generated targets built by string concatenation including parent references.
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: app target
- brew-cask: binary target
- brew-cask: generic artifact source is not contained by the…
- brew-cask: refusing generic artifact copy outside Homebrew…
- brew-cask: refusing installer executable outside trusted…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/c7f6f270130c4f3a.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/mod.rs:2290
|| current_groups.contains(&stat.st_gid);
let writable_by_untrusted = stat.st_mode & 0o002 != 0
|| (stat.st_mode & 0o020 != 0 && (!allow_current_user || !trusted_group));
if !SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFDIR)
|| !trusted_owner
|| writable_by_untrusted
{
bail!(
"brew-cask: refusing operation through untrusted directory {}",
directory.display()
);
}
Ok(())
};
let mut directory = resolved_root.to_path_buf();
verify(&fd, &directory)?;
for component in relative.components() {
let Component::Normal(name) = component else {
bail!("brew-cask: invalid generic artifact parent");
};
directory.push(name);
fd = match openat(&fd, name, flags, Mode::empty()) {
Ok(fd) => fd,
Err(nix::errno::Errno::ENOENT) if create_missing => {
match nix::sys::stat::mkdirat(
&fd,
name,
Mode::S_IRWXU | Mode::S_IRGRP | Mode::S_IXGRP | Mode::S_IROTH | Mode::S_IXOTH,
) {
Ok(()) | Err(nix::errno::Errno::EEXIST) => {}
Err(err) => {
return Err(err).wrap_err_with(|| {
format!(
"brew-cask: cannot create operation directory {}",
directory.display()
)
});View on GitHub (pinned to 533346cc37)