{"record":{"id":"f98ffef1c70801a0","repo":"jdx/mise","slug":"brew-cask-binary-target-contains-nul-f98ffe","errorCode":null,"errorMessage":"brew-cask: binary target contains NUL","messagePattern":"brew-cask: binary target contains NUL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/paths.rs","lineNumber":270,"sourceCode":"    }\n    Ok(roots)\n}\n\npub(super) fn is_appdir_binary_target(target_name: &str) -> bool {\n    target_name.starts_with(\"$APPDIR/\")\n}\n\npub(super) fn allowed_binary_target_roots_display(roots: &[PathBuf]) -> String {\n    roots\n        .iter()\n        .map(|root| root.display().to_string())\n        .collect::<Vec<_>>()\n        .join(\" or \")\n}\n\npub(super) fn binary_target_path(target_name: &str, appdir: &Path) -> Result<PathBuf> {\n    if target_name.contains('\\0') {\n        bail!(\"brew-cask: binary target contains NUL\");\n    }\n    if let Some(relative) = target_name.strip_prefix(\"$APPDIR/\") {\n        let relative = Path::new(relative);\n        reject_appdir_escape(relative, \"binary $APPDIR target\", target_name)?;\n        if !allowed_appdir_roots()?.iter().any(|root| root == appdir) {\n            bail!(\"brew-cask: invalid appdir '{}'\", appdir.display());\n        }\n        return Ok(appdir.join(relative));\n    }\n    if target_name.contains(\"$APPDIR\") {\n        bail!(\"brew-cask: $APPDIR must prefix a binary target\");\n    }\n    let prefix = prefix::prefix();\n    let prefix_str = prefix.to_string_lossy();\n    let target_name = target_name.replace(\"$HOMEBREW_PREFIX\", prefix_str.as_ref());\n    let path = PathBuf::from(&target_name);\n    let target = if path.is_absolute() {\n        path","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/paths.rs#L252-L288","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ntargets.iter().for_each(|t| { let _ = process(t); });\n// after\ntargets.iter().filter(|t| !t.contains('\\0')).for_each(|t| { let _ = process(t); });","handlingStrategy":"validation","validationCode":"fn sanitize_target(t: &str) -> Option<&str> {\n    if t.contains('\\0') { None } else { Some(t) }\n}","typeGuard":"fn has_no_nul(t: &str) -> bool { !t.as_bytes().contains(&b'\\0') }","tryCatchPattern":null,"preventionTips":["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."],"tags":["brew-cask","path-validation","input-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}