{"record":{"id":"f3e1225fd5dc7669","repo":"jdx/mise","slug":"brew-cask-nested-archive-depth-exceeds-max-neste","errorCode":null,"errorMessage":"brew-cask: nested archive depth exceeds {MAX_NESTED_CASK_ARCHIVES}","messagePattern":"brew-cask: nested archive depth exceeds (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/fetch.rs","lineNumber":345,"sourceCode":"            .to_string();\n        let nested = extract_dir.with_file_name(format!(\n            \".{}-nested-{depth}\",\n            extract_dir\n                .file_name()\n                .and_then(|name| name.to_str())\n                .unwrap_or(\"cask\")\n        ));\n        file::remove_all(&nested)?;\n        file::rename(&archive, &nested)?;\n        file::remove_all(extract_dir)?;\n        file::create_dir_all(extract_dir)?;\n        let result = extract_nested_cask_archive(&nested, extract_dir, &filename, pr);\n        let cleanup = file::remove_all(&nested);\n        result?;\n        cleanup?;\n    }\n    if single_nested_cask_archive(extract_dir)?.is_some() {\n        bail!(\"brew-cask: nested archive depth exceeds {MAX_NESTED_CASK_ARCHIVES}\");\n    }\n    Ok(())\n}\n\npub(super) fn single_nested_cask_archive(root: &Path) -> Result<Option<PathBuf>> {\n    let mut entries = std::fs::read_dir(root)?.filter(|entry| match entry {\n        Ok(entry) => entry.file_name() != \"__MACOSX\",\n        Err(_) => true,\n    });\n    let Some(entry) = entries.next().transpose()? else {\n        return Ok(None);\n    };\n    if entries.next().is_some() || !entry.file_type()?.is_file() {\n        return Ok(None);\n    }\n    let path = entry.path();\n    let filename = entry.file_name();\n    let filename = filename","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/fetch.rs#L327-L363","documentation":"Some cask archives contain another single archive inside (zip-in-zip). mise unpacks nested archives iteratively up to MAX_NESTED_CASK_ARCHIVES levels. If after the maximum iterations the extract directory still contains exactly one archive file, mise concludes the nesting exceeds the limit and aborts rather than looping forever (a zip-bomb guard).","triggerScenarios":"extract_nested_cask_archives, called from extract_archive, exhausts MAX_NESTED_CASK_ARCHIVES iterations and single_nested_cask_archive still finds one archive file in the extract dir — i.e. the artifact nests archives deeper than the configured maximum.","commonSituations":"An upstream artifact that ships a deeply nested zip-in-zip-in-zip; a malicious or misconfigured cask crafting a quasi-infinite nesting (zip-bomb); an extractor producing an archive instead of plain files at some level.","solutions":["Manually unpack the artifact to confirm its real nesting depth and check whether the cask points at the right file.","Find a flatter artifact URL for the cask (e.g. the direct app zip) and update the cask metadata.","If you maintain this code path and legitimate casks need more depth, raise MAX_NESTED_CASK_ARCHIVES deliberately.","Treat repeated occurrences as suspicious — verify the artifact against the cask's sha256 before trusting it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// check nesting depth of a downloaded artifact before relying on it\nunzip -l app.zip            # inspect entries; flag nested .zip/.tar members\nfind extract_dir -name '*.zip' -o -name '*.tar.gz' | wc -l","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Unpack candidate artifacts manually and prefer flat archives in cask URLs.","Always verify sha256 so tampered/nested payloads are rejected earlier.","Treat repeated depth failures as a possible zip-bomb and investigate the source."],"tags":["brew","archive","nesting-limit","security"],"backgroundTag":"value-out-of-range","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}