{"record":{"id":"b231c19c649b248e","repo":"jdx/mise","slug":"content-level-slsa-verification-does-not-support-s","errorCode":null,"errorMessage":"content-level SLSA verification does not support symlink archive entry: {}","messagePattern":"content-level SLSA verification does not support symlink archive entry: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/file.rs","lineNumber":2521,"sourceCode":"    validate_archive_content_files(files)\n}\n\nfn archive_content_files_zip(\n    archive_path: &Path,\n    strip_components: usize,\n) -> Result<Vec<ArchiveContent>> {\n    let f = File::open(archive_path)?;\n    let mut archive = ZipArchive::new(f)\n        .wrap_err_with(|| format!(\"failed to open zip archive: {}\", display_path(archive_path)))?;\n    let mut files = Vec::new();\n\n    for i in 0..archive.len() {\n        let mut file = archive.by_index(i)?;\n        if file.is_dir() {\n            continue;\n        }\n        if file.is_symlink() {\n            bail!(\n                \"content-level SLSA verification does not support symlink archive entry: {}\",\n                file.name()\n            );\n        }\n        let enclosed_name = file.enclosed_name().ok_or_else(|| {\n            eyre::eyre!(\n                \"content-level SLSA verification rejected unsafe zip path: {}\",\n                file.name()\n            )\n        })?;\n        let name = normalize_archive_content_path(&enclosed_name, strip_components)?;\n        let sha256 = sha256_reader(&mut file)?;\n        files.push(ArchiveContent { name, sha256 });\n    }\n\n    validate_archive_content_files(files)\n}\n","sourceCodeStart":2503,"sourceCodeEnd":2539,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/file.rs#L2503-L2539","documentation":"The zip branch of content-level SLSA verification explicitly rejects symlink entries (file.is_symlink()): a symlink's target is not content mise can hash and could point outside the archive. Directories are skipped; every remaining entry must be a regular file.","triggerScenarios":"A .zip asset containing symlink entries (stored with unix mode bits) is processed by archive_content_files while content-level verification is enabled.","commonSituations":"Zips built on Linux/macOS that preserve symlinks, e.g. a bin directory with versioned symlinks created by zip without dereferencing.","solutions":["Fall back to artifact-level verification for that tool","If you produce the zip, repack with symlinks dereferenced (avoid zip -y, or dereference before zipping)","Use a tar.gz variant only if it also contains no links (the tar path rejects them too)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let mut za = zip::ZipArchive::new(std::fs::File::open(&archive)?)?;\nfor i in 0..za.len() {\n    let f = za.by_index(i)?;\n    if f.is_symlink() {\n        anyhow::bail!(\"zip contains symlink entry {}; content-level SLSA will fail closed\", f.name());\n    }\n}","typeGuard":null,"tryCatchPattern":"match archive_content_files(&archive, ExtractionFormat::Zip, strip) {\n    Ok(files) => verify_subjects(&files)?,\n    Err(e) if e.to_string().contains(\"symlink archive entry\") => {\n        warn!(\"zip contains symlinks; falling back to artifact-level verification: {e:#}\");\n        verify_artifact_level(&archive)?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Create zips without preserving symlinks (do not use zip -y; dereference before packing)","Check zip contents with unzip -l --verbose (mode bits) when link entries are possible"],"tags":["slsa","verification","zip","symlink","archive","rust","mise"],"backgroundTag":"archive-symlink-entry","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}