jdx/mise · error
invalid tap formula name '{name}'
Error message
invalid tap formula name '{name}' What it means
validate_name rejects tap formula/cask names that are empty, contain path separators ('/', '\\', NUL), equal '.' or '..', or whose PathBuf representation is not exactly one component. This guards against path traversal and malformed names being used to construct file paths inside the tap checkout.
Source
Thrown at src/system/packages/brew/tap.rs:364
];
let mut last_error = None;
for path in paths {
match HTTP_FETCH.get_text(format!("{raw_base}/{path}")).await {
Ok(source) => return Ok((source, path)),
Err(err) => last_error = Some(err),
}
}
Err(last_error.unwrap()).wrap_err_with(|| format!("tap has no {directory}/{name}.rb"))
}
fn validate_name(name: &str) -> Result<()> {
if name.is_empty()
|| name.contains(['/', '\\', '\0'])
|| name == "."
|| name == ".."
|| PathBuf::from(name).components().count() != 1
{
bail!("invalid tap formula name '{name}'");
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
async fn test_ruby() -> Result<Option<PathBuf>> {
if let Some(ruby) = usable_system_ruby().await {
return Ok(Some(ruby));
}
super::super::source::installed_ruby_bin().await
}
#[test]
fn rejects_unsafe_formula_names() {
for name in ["", ".", "..", "../oops", "a/b", "a\\b"] {View on GitHub (pinned to afd2eddd3a)
Solutions
- Pass only the bare formula/cask file stem (no directories, no tap prefix).
- Strip the tap name and directory components before calling, e.g. take the file_stem of the .rb path.
- Reject or sanitize input containing '/' or '\\' before invoking.
- If the name comes from an untrusted tap, treat this as an invalid/tampered tap and skip or re-clone it.
Example fix
// before formula_from_ruby(tap, "homebrew/core/wget", ruby_source).await?; // after formula_from_ruby(tap, "wget", ruby_source).await?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_tap_formula_name(name: &str) -> bool {
!name.is_empty()
&& !name.contains(['/', '\\', '\0'])
&& name != "."
&& name != ".."
&& std::path::Path::new(name).components().count() == 1
} Type guard
fn as_bare_formula_name(s: &str) -> Option<&str> {
let n = std::path::Path::new(s).file_name()?.to_str()?;
let n = n.strip_suffix(".rb").unwrap_or(n);
if n.is_empty() || n == "." || n == ".." { None } else { Some(n) }
} Try / catch
match formula_from_ruby(tap, name, src).await {
Err(e) if e.to_string().starts_with("invalid tap formula name") => {
eprintln!("skipping malformed entry: {name}");
Ok(None)
}
other => other.map(Some),
} Prevention
- Always pass the bare formula/cask file stem, never a tap-prefixed or path-qualified name
- Derive names via Path::file_name()/file_stem() from tap file paths
- Treat names containing '/' or '..' from untrusted taps as suspicious and skip them
When it happens
Trigger: formula_from_ruby or cask_from_ruby is given a name extracted from a tap's file path or user request that is empty, includes slashes/backslashes, is '.'/'..', or otherwise spans multiple path components.
Common situations: A formula name passed as 'user/repo/formula' instead of just 'formula'; malicious or corrupted tap file names containing '..' or separators; misparsed Ruby filenames; passing a fully qualified tap+name string where only the bare name is expected.
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 casks are installed at their current version ('{p}')
- brew-cask: requested token '{requested_token}' does not matc
- brew-cask: invalid {kind} '{value}'
- receipt target inventory contains an unclassified path
- the packslip names an executable {:?}, which is not a plain
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/c743010e65aebd84.
Report an issue: GitHub.