{"record":{"id":"cba392a4d97effb9","repo":"jdx/mise","slug":"registry-archive-is-too-large","errorCode":null,"errorMessage":"registry archive is too large","messagePattern":"registry archive is too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/registry.rs","lineNumber":383,"sourceCode":"}\n\nfn track_registry_archive_entry(\n    index: usize,\n    entry_size: u64,\n    archive_size: &mut u64,\n) -> Result<()> {\n    ensure!(\n        index < MAX_REGISTRY_ARCHIVE_ENTRIES,\n        \"registry archive contains too many entries\"\n    );\n    ensure!(\n        entry_size <= MAX_REGISTRY_ARCHIVE_ENTRY_SIZE,\n        \"registry archive entry is too large\"\n    );\n    *archive_size = archive_size\n        .checked_add(entry_size)\n        .ok_or_else(|| eyre::eyre!(\"registry archive size overflow\"))?;\n    ensure!(\n        *archive_size <= MAX_REGISTRY_ARCHIVE_SIZE,\n        \"registry archive is too large\"\n    );\n    Ok(())\n}\n\nfn registry_from_sources(sources: BTreeMap<String, String>) -> Result<Registry> {\n    let mut entries = BTreeMap::new();\n    let mut missing_version_order = false;\n    for (short, source) in sources {\n        let value: toml::Value = toml::from_str(&source)\n            .wrap_err_with(|| format!(\"failed to parse registry/{short}.toml\"))?;\n        let (tool, tool_missing_version_order) = parse_registry_tool(&short, &value)\n            .wrap_err_with(|| format!(\"invalid registry/{short}.toml\"))?;\n        missing_version_order |= tool_missing_version_order;\n        entries.insert(short, tool.clone());\n        for alias in tool.aliases {\n            entries.insert((*alias).to_string(), tool.clone());","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/registry.rs#L365-L401","documentation":"mise accumulates the total uncompressed size of all registry archive entries and enforces MAX_REGISTRY_ARCHIVE_SIZE. When the running sum exceeds the cap, parsing aborts. Together with the per-entry and per-count caps this bounds the worst-case cost of parsing an untrusted archive.","triggerScenarios":"track_registry_archive_entry, called for each entry in parse_registry_archive, when the accumulated entry sizes exceed MAX_REGISTRY_ARCHIVE_SIZE (after a checked add that would also guard overflow).","commonSituations":"Decompression-bomb style archives that are individually small entries but huge in total, corrupted or tampered registry downloads, or publishers shipping bloated archives full of non-registry data.","solutions":["Re-download the registry archive from a trusted source and clear the mise registry cache (`mise cache clear`).","Check total uncompressed size (`tar -tvzf archive.tar.gz | awk '{s+=$3} END{print s}'`) to confirm the archive is bloated.","If you publish the registry, slim the archive: exclude non-registry files, minify entry TOMLs, or split the registry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# shell: sum uncompressed sizes and compare to the archive-size cap\ntotal=$(tar -tvzf registry.tar.gz | awk '{s+=$3} END{print s}'); echo \"total uncompressed: $total\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Monitor total uncompressed registry size in CI as part of the release checklist.","Minify entry TOMLs and exclude non-registry content to keep archives slim.","Validate downloads against published checksums to detect bomb-style corruption."],"tags":["security","archive","resource-limit","registry"],"backgroundTag":"file-size-limit-exceeded","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"}