jdx/mise · error

brew-cask: invalid font target '{}'

Error message

brew-cask: invalid font target '{}'

What it means

When computing the destination path for a cask font, mise validates the declared font name as a relative path: it must not be absolute, must not contain `..` components, and must not be empty. This error guards against cask definitions (or hostile cask files) writing fonts outside the managed font directory — a path traversal safeguard.

Source

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

            .filter(|entry| entry.file_type().is_ok_and(|ft| ft.is_dir()))
            .any(|entry| relative.is_some_and(|path| entry.path().join(path).is_file()));
        if has_staged_copy {
            file::remove_file(target)?;
        }
    }
    Ok(())
}

fn font_target_path(font: &FontArtifact) -> Result<PathBuf> {
    let name = font_filename(font)?;
    let name_path = Path::new(&name);
    if name_path.is_absolute()
        || name_path
            .components()
            .any(|component| matches!(component, Component::ParentDir))
        || name_path.components().next().is_none()
    {
        bail!("brew-cask: invalid font target '{}'", name);
    }
    Ok(font_dir().join(name_path))
}

fn font_dir() -> PathBuf {
    if cfg!(target_os = "linux") {
        crate::env::XDG_DATA_HOME.join("fonts")
    } else {
        crate::dirs::HOME.join("Library").join("Fonts")
    }
}

fn stage_completion(
    stage: &Path,
    caskroom: &Path,
    cask: &Cask,
    apps: &[AppArtifact],
    completion: &CompletionArtifact,

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Fix the font name in the cask definition to a plain relative filename like "SomeFont.ttf"
  2. Do not use absolute paths or `..` in font stanzas; place subpath fonts under a relative directory if needed
  3. Only use casks from trusted sources; treat this error as a blocked malicious/incorrect cask

Example fix

// before (cask stanza)
font "../../evil.ttf"
// after
font "MyFont.ttf"
Defensive patterns

Strategy: validation

Validate before calling

let p = Path::new(name);
assert!(!p.is_absolute() && !p.components().any(|c| matches!(c, std::path::Component::ParentDir)) && p.components().next().is_some(), "font target must be a relative, non-empty path");

Type guard

fn is_safe_relative_name(name: &str) -> bool {
  let p = std::path::Path::new(name);
  !p.is_absolute()
    && p.components().next().is_some()
    && !p.components().any(|c| matches!(c, std::path::Component::ParentDir))
}

Try / catch

if let Err(e) = result {
  if e.contains("invalid font target") {
    eprintln!("cask font target rejected as unsafe; fix the cask's font stanza to a relative filename");
  }
}

Prevention

When it happens

Trigger: `font_target_path` builds a relative `PathBuf` from the font name and finds `name_path.is_absolute()`, any `Component::ParentDir`, or zero components before returning `font_dir().join(name_path)`.

Common situations: A hand-edited or third-party cask declares `font "~/Library/Fonts/x.ttf"` (absolute/tilded) or `"../../evil.ttf"`; a cask stanza with an empty font name after variable expansion.

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/024c97f093f4ef74. Report an issue: GitHub.