jdx/mise · error
brew-cask: app target contains NUL
Error message
brew-cask: app target contains NUL
What it means
`app_target_path` validates the destination path for an app artifact before any filesystem work. If the target name contains a NUL byte (`\0`), which no Unix path can contain, the function bails immediately. This is an early input-validation guard against unusable or malicious path strings.
Solutions
- Inspect the app target string for non-printable bytes (e.g. `grep -P '\\x00'` or `xxd`) in your config or the cask definition and remove/repair it.
- Re-write the affected config value by hand rather than pasting, to eliminate invisible control characters.
- If the value comes from a downloaded cask definition, refresh it or pin a known-good cask version.
Example fix
// before (target read from corrupted source contains \0) let target = String::from_utf8_lossy(raw_bytes).to_string(); // after (strip NUL/control bytes before use) let target: String = raw.chars().filter(|c| !c.is_control()).collect();
Defensive patterns
Strategy: validation
Validate before calling
if target_name.contains('\0') {
return Err("app target contains NUL byte".into());
} Type guard
fn is_nul_free(s: &str) -> bool { !s.contains('\0') } Try / catch
if let Err(e) = app_target_path(&target_name) {
if e.to_string().contains("NUL") {
// sanitize or reject the input before retrying
}
} Prevention
- Sanitize strings read from files/network: strip control characters before using them as paths.
- Never paste target values from binary sources; retype them.
- Treat cask metadata as untrusted input and validate it before use.
When it happens
Trigger: Calling any of `installed_skip_reason`, `app_target_paths`, `install_app`, `validate_adoptable_apps`, or `appdir_artifact_source` with an app target string containing an embedded NUL byte — typically from corrupted config, hostile cask metadata, or a bad string decode.
Common situations: Hand-edited mise.toml or a cask override where a pasted value includes a hidden NUL; data read from a binary-corrupted file; an attacker-supplied cask name probing path handling.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- brew-cask: binary target contains NUL
- brew-cask: ' ' must be an absolute path
- brew-cask: ' ' must not resolve to the filesystem root
- brew-cask: app target
- brew-cask: app target
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/4c390c2b5c8b2248.
Report an issue: GitHub.
Appendix: 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 533346cc37)