jdx/mise · error
brew-cask: app target contains NUL
Error message
brew-cask: app target contains NUL
What it means
app_target_path rejects app target names containing NUL bytes because Rust PathBuf and the filesystem APIs cannot represent embedded NULs; such a target is necessarily invalid. The check runs before any path construction or install work.
Source
Thrown at src/system/packages/brew/cask/paths.rs:115
};
let matches = match (a, b) {
(Component::Normal(a), Component::Normal(b)) => match (a.to_str(), b.to_str()) {
(Some(a), Some(b)) => a.eq_ignore_ascii_case(b),
_ => a == b,
},
_ => a == b,
};
if !matches {
return false;
}
}
true
}
pub(super) fn app_target_path(target_name: &str) -> Result<PathBuf> {
let app_dir = target_app_dir()?;
if target_name.contains('\0') {
bail!("brew-cask: app target contains NUL");
}
if target_name.contains('/') {
let target = target_name.replace("$HOMEBREW_PREFIX", &prefix::prefix().to_string_lossy());
let path = PathBuf::from(target);
if path
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!("brew-cask: app target '{target_name}' must not contain '..'");
}
if path.is_absolute() {
let prefix_app_dir = prefix::prefix().join("Applications");
if path.starts_with(&app_dir) || path.starts_with(&prefix_app_dir) {
return Ok(path);
}
// Casks routinely hardcode an absolute `/Applications/Foo.app`
// target. When an override appdir is configured, relocate such a
// target into it (preserving any subdirectories) rather thanView on GitHub (pinned to afd2eddd3a)
Solutions
- Strip or reject NUL characters from the target name before installing the app
- Re-fetch the cask metadata from the trusted upstream source
- Sanitize inputs at the deserialization boundary so embedded NULs never reach path construction
Example fix
// before
let target_name = raw_target; // may contain '\0'
// after
let target_name = raw_target.trim_end_matches('\0'); Defensive patterns
Strategy: validation
Validate before calling
if target_name.contains('\0') {
return Err("app target contains NUL byte");
} Type guard
fn is_safe_target(s: &str) -> bool {
!s.is_empty() && !s.contains('\0') && !s.contains('\u{0}')
} Try / catch
match install_result {
Err(e) if e.to_string().contains("NUL") => {
eprintln!("cask metadata is corrupt; refetching");
refetch_cask_metadata();
}
_ => {}
} Prevention
- Sanitize strings at the JSON/deserialization boundary for embedded NULs
- Treat cask metadata from untrusted sources as hostile and validate all path fields
When it happens
Trigger: Calling app_target_path (directly or via installed_skip_reason, app_target_paths, install_app, etc.) with a target_name string containing '\0', typically from untrusted cask metadata or malformed JSON input.
Common situations: Corrupt or hostile cask metadata whose target field embeds a NUL, a truncation bug upstream producing a padded string, or binary data accidentally parsed into the target field.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- brew-cask: refusing generic artifact copy outside Homebrew p
- brew-cask: invalid generic artifact parent
- brew-cask: generic artifact target '{}' must stay below {}
- brew-cask: invalid font target '{}'
- brew-cask: invalid structured flight path '{}'
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/4c390c2b5c8b2248.
Report an issue: GitHub.