LykosAI/StabilityMatrix · error · ExtractionException

Entry is trying to create a directory outside of the…

Error message

Entry is trying to create a directory outside of the destination directory.

What it means

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.

Solutions

  1. Treat this as the archive being unsafe — do not bypass the check; inspect the archive's entry paths with 7z l
  2. Repackage the archive with relative, sanitized entry paths (strip leading slashes and '..' segments) from a trusted source
  3. Only extract archives from trusted, checksum-verified sources
  4. If you control archive creation, sanitize entry names at packaging time

Example fix

// before
var safeName = entry.FullName;
// after
var safeName = string.Join('/', entry.FullName.Split('/', '\\')
    .Where(seg => seg != ".." && seg != "." && !Path.IsPathRooted(seg)));
Defensive patterns

Strategy: try-catch

Validate before calling

using var archive = File.OpenRead(archivePath);
using var za = new ZipArchive(archive);
foreach (var e in za.Entries)
{
    var dest = Path.GetFullPath(Path.Combine(destDir, e.FullName));
    if (!dest.StartsWith(Path.GetFullPath(destDir), StringComparison.Ordinal))
        throw new InvalidDataException($"Unsafe entry path: {e.FullName}");
}

Type guard

static bool IsSafeEntryPath(string destDir, string entryName)
{
    var dest = Path.GetFullPath(Path.Combine(destDir, entryName));
    return dest.StartsWith(Path.GetFullPath(destDir), StringComparison.Ordinal);
}

Try / catch

try { ArchiveHelper.ExtractManaged(archivePath, destDir); }
catch (ExtractionException ex) when (ex.Message.Contains("outside of the destination directory"))
{
    logger.LogError(ex, "Rejected archive with path-traversal entries");
    // quarantine/delete the archive; do not retry
    File.Delete(archivePath);
}

Prevention

When it happens

Trigger: An archive entry path contains '../' segments, absolute paths, or drive-like prefixes so that Path.GetFullPath(Path.Combine(fullOutputDir, folder)) escapes fullOutputDir.

Common situations: 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.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of LykosAI/StabilityMatrix@af93d6ef57 (2026-09-12). Data as JSON: /api/errors/4f91a144e839b5e7. Report an issue: GitHub.

Appendix: source

Thrown at StabilityMatrix.Core/Helper/ArchiveHelper.cs:335

            var outputPath = Path.Combine(outputDirectory, entry.Key);

            if (entry.IsDirectory)
            {
                if (!Directory.Exists(outputPath))
                {
                    Directory.CreateDirectory(outputPath);
                }
            }
            else
            {
                var folder = Path.GetDirectoryName(entry.Key)!;
                var destDir = Path.GetFullPath(Path.Combine(fullOutputDir, folder));

                if (!Directory.Exists(destDir))
                {
                    if (!destDir.StartsWith(fullOutputDir, StringComparison.Ordinal))
                    {
                        throw new ExtractionException(
                            "Entry is trying to create a directory outside of the destination directory."
                        );
                    }

                    Directory.CreateDirectory(destDir);
                }

                // Check if symbolic link
                if (entry.LinkTarget != null)
                {
                    // Not sure why but symlink entries have a key that ends with a space
                    // and some broken path suffix, so we'll remove everything after the last space
                    Logger.Debug(
                        $"Checking if output path {outputPath} contains space char: {outputPath.Contains(' ')}"
                    );
                    if (outputPath.Contains(' '))
                    {
                        outputPath = outputPath[..outputPath.LastIndexOf(' ')];

View on GitHub (pinned to af93d6ef57)