{"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":2712,"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":2694,"sourceCodeEnd":2730,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/file.rs#L2694-L2730","documentation":"During zip content hashing for SLSA verification, mise skips directories but rejects any symlink entries, since content verification hashes regular file data only and symlinks cannot be verified the same way (and may be attack vectors). The member name is included in the error.","triggerScenarios":"SLSA content verification of a zip archive that stores symlinks among its entries.","commonSituations":"Zips created on Unix with `zip -y` preserving symlinks; GitHub-generated source archives; packaging pipelines that include symlinked libs.","solutions":["Repackage the zip with real files instead of symlinks","Create the zip without symlink preservation so targets are stored as files","Use tar.* (if verification supported it) or disable content verification for this asset"],"exampleFix":"// before\nzip -r tool.zip tool/   # preserves symlinks\n// after\nzip -r tool.zip -D tool/   # or dereference/replace symlinks before zipping","handlingStrategy":"try-catch","validationCode":"// list zip entries and reject symlink metadata before verification\nfor (const e of listZip(archive)) {\n  if (e.isSymlink) throw new Error(\"symlink entry: \" + e.name);\n}","typeGuard":"function isRegularZipEntry(e) { return !e.isSymlink && !e.isDirectory; }","tryCatchPattern":"try { verifySlsaZip(a) } catch (e) { if (/symlink archive entry/.test(e.message)) { repackZipWithoutSymlinks(a); } else throw e; }","preventionTips":["Create zips without symlink preservation (`zip -D` or dereference first)","Avoid shipping zips that contain symlinks","Check zip listings before enabling content verification"],"tags":["slsa","verification","zip","symlink"],"backgroundTag":"unsupported-operation","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}