{"record":{"id":"4f91a144e839b5e7","repo":"LykosAI/StabilityMatrix","slug":"entry-is-trying-to-create-a-directory-outside-of-the","errorCode":null,"errorMessage":"Entry is trying to create a directory outside of the destination directory.","messagePattern":"Entry is trying to create a directory outside of the destination directory\\.","errorType":"exception","errorClass":"ExtractionException","httpStatus":null,"severity":"error","filePath":"StabilityMatrix.Core/Helper/ArchiveHelper.cs","lineNumber":335,"sourceCode":"            var outputPath = Path.Combine(outputDirectory, entry.Key);\n\n            if (entry.IsDirectory)\n            {\n                if (!Directory.Exists(outputPath))\n                {\n                    Directory.CreateDirectory(outputPath);\n                }\n            }\n            else\n            {\n                var folder = Path.GetDirectoryName(entry.Key)!;\n                var destDir = Path.GetFullPath(Path.Combine(fullOutputDir, folder));\n\n                if (!Directory.Exists(destDir))\n                {\n                    if (!destDir.StartsWith(fullOutputDir, StringComparison.Ordinal))\n                    {\n                        throw new ExtractionException(\n                            \"Entry is trying to create a directory outside of the destination directory.\"\n                        );\n                    }\n\n                    Directory.CreateDirectory(destDir);\n                }\n\n                // Check if symbolic link\n                if (entry.LinkTarget != null)\n                {\n                    // Not sure why but symlink entries have a key that ends with a space\n                    // and some broken path suffix, so we'll remove everything after the last space\n                    Logger.Debug(\n                        $\"Checking if output path {outputPath} contains space char: {outputPath.Contains(' ')}\"\n                    );\n                    if (outputPath.Contains(' '))\n                    {\n                        outputPath = outputPath[..outputPath.LastIndexOf(' ')];","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/LykosAI/StabilityMatrix/blob/af93d6ef57c01cd890d7e0ad0a9ea8c9fcda3002/StabilityMatrix.Core/Helper/ArchiveHelper.cs#L317-L353","documentation":"ExtractManaged defends against Zip Slip / path traversal: when an archive entry would create a directory, the resolved destination is checked to be inside the output directory (ordinal prefix comparison). If a crafted or malformed entry resolves outside it, ExtractionException is thrown and extraction aborts.","triggerScenarios":"An archive entry path contains '../' segments, absolute paths, or drive-like prefixes so that Path.GetFullPath(Path.Combine(fullOutputDir, folder)) escapes fullOutputDir.","commonSituations":"Maliciously crafted model packages or archives generated on Windows with absolute entry names; archives built with tools writing 'C:\\...' or '../' entry paths; untrusted community downloads.","solutions":["Treat this as the archive being unsafe — do not bypass the check; inspect the archive's entry paths with 7z l","Repackage the archive with relative, sanitized entry paths (strip leading slashes and '..' segments) from a trusted source","Only extract archives from trusted, checksum-verified sources","If you control archive creation, sanitize entry names at packaging time"],"exampleFix":"// before\nvar safeName = entry.FullName;\n// after\nvar safeName = string.Join('/', entry.FullName.Split('/', '\\\\')\n    .Where(seg => seg != \"..\" && seg != \".\" && !Path.IsPathRooted(seg)));","handlingStrategy":"try-catch","validationCode":"using var archive = File.OpenRead(archivePath);\nusing var za = new ZipArchive(archive);\nforeach (var e in za.Entries)\n{\n    var dest = Path.GetFullPath(Path.Combine(destDir, e.FullName));\n    if (!dest.StartsWith(Path.GetFullPath(destDir), StringComparison.Ordinal))\n        throw new InvalidDataException($\"Unsafe entry path: {e.FullName}\");\n}","typeGuard":"static bool IsSafeEntryPath(string destDir, string entryName)\n{\n    var dest = Path.GetFullPath(Path.Combine(destDir, entryName));\n    return dest.StartsWith(Path.GetFullPath(destDir), StringComparison.Ordinal);\n}","tryCatchPattern":"try { ArchiveHelper.ExtractManaged(archivePath, destDir); }\ncatch (ExtractionException ex) when (ex.Message.Contains(\"outside of the destination directory\"))\n{\n    logger.LogError(ex, \"Rejected archive with path-traversal entries\");\n    // quarantine/delete the archive; do not retry\n    File.Delete(archivePath);\n}","preventionTips":["Only extract archives from trusted, checksum-verified sources","Pre-scan entry paths for '..' and rooted paths before extraction","Reject (not sanitize) malicious archives and report them","Sanitize entry names when you create archives"],"tags":["security","path-traversal","zip-slip","archive"],"backgroundTag":"path-traversal-blocked","analyzedSha":"af93d6ef57c01cd890d7e0ad0a9ea8c9fcda3002","analyzedAt":"2026-09-12T19:02:43.389Z","contentChangedAt":"2026-09-12T19:02:43.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}