jdx/mise · error

brew-cask: structured flight glob '{}' matched outside stage

Error message

brew-cask: structured flight glob '{}' matched outside staged path

What it means

A structured flight glob expanded to a path outside the cask's staged directory. Homebrew restricts all glob-based flight operations to within the staging area to prevent casks from reading/moving arbitrary filesystem paths, and throws this as a safety guard (potential malicious or buggy cask).

Source

Thrown at src/system/packages/brew/cask/flight.rs:1034

    let escaped_root = glob::Pattern::escape(staged_path.to_string_lossy().as_ref());
    for pattern in expand_braces(pattern) {
        validate_flight_relative_path(&pattern)?;
        let rooted_pattern = Path::new(&escaped_root)
            .join(Path::new(&pattern))
            .to_string_lossy()
            .to_string();
        for path in glob::glob_with(
            &rooted_pattern,
            glob::MatchOptions {
                require_literal_separator: true,
                ..Default::default()
            },
        )
        .wrap_err_with(|| format!("brew-cask: invalid structured flight glob '{pattern}'"))?
        {
            let path = path?;
            if !path.starts_with(staged_path) {
                bail!(
                    "brew-cask: structured flight glob '{}' matched outside staged path",
                    pattern
                );
            }
            matches.push(path);
        }
    }
    matches.sort();
    matches.dedup();
    Ok(matches)
}

pub(super) fn is_flight_glob(path: &str) -> bool {
    path.chars()
        .any(|c| matches!(c, '*' | '?' | '[' | ']' | '{' | '}'))
}

pub(super) fn resolve_flight_path(staged_path: &Path, path: &FlightPath) -> Result<PathBuf> {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Remove any `..` or absolute components from the glob pattern
  2. Ensure matched paths are real staged artifacts, not out-of-stage symlinks
  3. Anchor the glob under the intended staged subdirectory
  4. Audit the cask with `brew audit` before installing

Example fix

// before
glob: staged_path.join("../shared/*.framework")
// after
glob: staged_path.join("lib/*.framework")
Defensive patterns

Strategy: validation

Validate before calling

fn stays_in_stage(staged: &Path, m: &Path) -> bool {
    m.starts_with(staged) && !m.components().any(|c| c == std::path::Component::ParentDir)
}

Prevention

When it happens

Trigger: A cask glob uses `..` components, absolute expansion, or symlinks such that matched paths escape `staged_path` — e.g. pattern `../Shared/*` or matching a symlink pointing outside the stage.

Common situations: Malicious or mis-authored casks attempting to escape staging; casks whose glob matches symlinked directories that point elsewhere on disk.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/e82059685551519e. Report an issue: GitHub.