jdx/mise · error
brew-cask: binary target contains NUL
Error message
brew-cask: binary target contains NUL
What it means
A cask `binary` artifact target containing an embedded NUL byte is rejected by binary_target_path before any path construction, because NUL terminates C strings on Unix and such a target can never name a valid file (src/system/packages/brew/cask/paths.rs:270). This is a strict input-integrity check on target names coming from cask stanzas or user configuration.
Solutions
- Inspect the cask's binary stanza and remove the NUL byte; fix the cask source or re-download it from the trusted tap.
- If the target name comes from program data, decode it as UTF-8 text and validate it contains no '\0' before passing it to the cask APIs (e.g. filter |t| !t.contains('\0')).
- Check the producing tool/format for a bug that embeds NULs (e.g. reading NUL-padded fixed-size buffers without trimming).
- Report tampering if the NUL appears in a cask you did not author — NUL injection in paths is a classic sanitizer-evasion vector.
Example fix
// before
targets.iter().for_each(|t| { let _ = process(t); });
// after
targets.iter().filter(|t| !t.contains('\0')).for_each(|t| { let _ = process(t); }); Defensive patterns
Strategy: validation
Validate before calling
fn sanitize_target(t: &str) -> Option<&str> {
if t.contains('\0') { None } else { Some(t) }
} Type guard
fn has_no_nul(t: &str) -> bool { !t.as_bytes().contains(&b'\0') } Prevention
- Always decode target names from cask metadata as strict UTF-8 text; never pass raw bytes.
- Trim NUL padding when reading fixed-size string fields from binary formats.
- Validate all externally sourced target names for '\0' (and other control characters) at the trust boundary.
- Treat NUL-in-path data from untrusted casks as tampering and reject the whole source.
When it happens
Trigger: A cask's `binary` stanza (or a user-supplied binary target) contains a literal or injected NUL byte, e.g. from binary_target_path being called with a target_name string read from corrupted or malicious cask data. Called via target_path and binary_targets_must_stay_under_an_allowed_root during install/validation.
Common situations: Corrupted or tampered custom cask definitions; binary-safe data (e.g. from a byte buffer or binary file) accidentally passed as the target name instead of decoded UTF-8 text; untrimmed NUL-padded fixed-size fields from cask metadata producers.
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: app 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/f98ffef1c70801a0.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/paths.rs:270
}
Ok(roots)
}
pub(super) fn is_appdir_binary_target(target_name: &str) -> bool {
target_name.starts_with("$APPDIR/")
}
pub(super) fn allowed_binary_target_roots_display(roots: &[PathBuf]) -> String {
roots
.iter()
.map(|root| root.display().to_string())
.collect::<Vec<_>>()
.join(" or ")
}
pub(super) fn binary_target_path(target_name: &str, appdir: &Path) -> Result<PathBuf> {
if target_name.contains('\0') {
bail!("brew-cask: binary target contains NUL");
}
if let Some(relative) = target_name.strip_prefix("$APPDIR/") {
let relative = Path::new(relative);
reject_appdir_escape(relative, "binary $APPDIR target", target_name)?;
if !allowed_appdir_roots()?.iter().any(|root| root == appdir) {
bail!("brew-cask: invalid appdir '{}'", appdir.display());
}
return Ok(appdir.join(relative));
}
if target_name.contains("$APPDIR") {
bail!("brew-cask: $APPDIR must prefix a binary target");
}
let prefix = prefix::prefix();
let prefix_str = prefix.to_string_lossy();
let target_name = target_name.replace("$HOMEBREW_PREFIX", prefix_str.as_ref());
let path = PathBuf::from(&target_name);
let target = if path.is_absolute() {
pathView on GitHub (pinned to 533346cc37)