jdx/mise · error
brew-cask: invalid structured flight path '{}'
Error message
brew-cask: invalid structured flight path '{}' What it means
`validate_flight_relative_path` rejects flight paths that are absolute or contain a `..` (ParentDir) component. It is the traversal guard applied to every path joined onto the staged root, so structured steps cannot reach files outside the staging sandbox.
Source
Thrown at src/system/packages/brew/cask.rs:4038
.replace("{{staged_path}}", &staged_path.to_string_lossy())
.replace("{{appdir}}", &appdir.to_string_lossy());
if let Some(version) = version {
value = value.replace("{{version}}", version);
}
if let Some(rest) = value.strip_prefix("~/") {
value = crate::dirs::HOME.join(rest).to_string_lossy().to_string();
}
value
}
fn validate_flight_relative_path(path: &str) -> Result<()> {
let path = Path::new(path);
if path.is_absolute()
|| path
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!(
"brew-cask: invalid structured flight path '{}'",
path.display()
);
}
Ok(())
}
fn expand_braces(pattern: &str) -> Vec<String> {
let Some(start) = pattern.find('{') else {
return vec![pattern.to_string()];
};
let Some(end_offset) = pattern[start + 1..].find('}') else {
return vec![pattern.to_string()];
};
let end = start + 1 + end_offset;
let prefix = &pattern[..start];
let suffix = &pattern[end + 1..];
let mut expanded = Vec::new();View on GitHub (pinned to 6f52dcdf99)
Solutions
- Rewrite the path relative to the staged root with no `..` components
- Use an artifact form and base that legitimately supports the location instead of smuggling absolute paths
- Sanitize template output before it lands in a staged-relative field
Example fix
# before move(source: "../../shared/lib.dylib", target: "lib/lib.dylib") # after move(source: "shared/lib.dylib", target: "lib/lib.dylib")
Defensive patterns
Strategy: validation
Validate before calling
// Reject absolute or parent-escaping relative paths before they reach the resolver
fn is_safe_relative_path(p: &str) -> bool {
let path = std::path::Path::new(p);
!path.is_absolute()
&& !path
.components()
.any(|c| matches!(c, std::path::Component::ParentDir))
} Try / catch
if err.to_string().contains("invalid structured flight path") {
// rewrite the offending path staged-relative; do not attempt to whitelist `..` segments
} Prevention
- Lint cask stanzas for absolute paths and `..` segments
- Sanitize template output before it becomes a flight path
- Treat this guard as non-negotiable: it is the staging sandbox boundary
When it happens
Trigger: A cask stanza path like `../shared/lib.x` or `/Applications/Foo.app` where a staged-relative path is required; a template expanding to a value that begins with `/`; concatenation bugs leaving `..` segments in the string.
Common situations: Porting ruby stanzas that use absolute paths; a user-edited cask trying to share payloads across casks; version strings injecting a leading separator.
Related errors
- brew-cask: APPDIR artifact '{source}' must stay below Applic
- brew-cask:{}: invalid {kind} run command path {}
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/fad693e01ad4a63f.
Report an issue: GitHub.