microsoft/aspire · error · InvalidOperationException

Tar entry ' ' would extract outside the destination…

Error message

Tar entry '{entry.Name}' would extract outside the destination directory.

What it means

ExtractTarGzSafe validates each tar entry's resolved path against the normalized destination directory and throws InvalidOperationException if the entry would extract outside it. This guards against tar-slip path traversal via '..' segments or absolute entry names.

Solutions

  1. Download the archive from the official/trusted source and verify integrity.
  2. List entry names (tar -tzf) to find offending entries and repack with relative paths.
  3. Fix your packaging script if it created entries with absolute or '..' names.

Example fix

// before
// tar entry: "/etc/evil" (absolute path entry)
// after
// repack with relative entries: "bin/evil" -> correct relative path
Defensive patterns

Strategy: try-catch

Validate before calling

await using var stream = File.OpenRead(tarGzPath);
await using var gz = new GZipStream(stream, CompressionMode.Decompress);
using var tar = new TarReader(gz);
var destFull = Path.GetFullPath(destinationPath);
while (await tar.GetNextEntryAsync() is { } entry)
{
    var p = Path.GetFullPath(Path.Combine(destFull, entry.Name));
    if (!p.StartsWith(destFull + Path.DirectorySeparatorChar, StringComparison.Ordinal)) throw new InvalidOperationException($"Unsafe entry: {entry.Name}");
}

Try / catch

try { await ArchiveHelper.ExtractAsync(tgzPath, dest, env, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Tar entry")) { // reject untrusted archive
}

Prevention

When it happens

Trigger: Extracting a tar.gz containing entries whose Name resolves outside the destination after GetFullPath(Path.Combine(destination, entry.Name)).

Common situations: Untrusted or tampered archives; archives built on systems that stored absolute paths in entry names; corrupted 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 microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/7635c654c5304899. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Utils/ArchiveHelper.cs:92

        await using var fileStream = new FileStream(archivePath, FileMode.Open, FileAccess.Read);
        await using var gzipStream = new GZipStream(fileStream, CompressionMode.Decompress);
        await using var tarReader = new TarReader(gzipStream);

        while (await tarReader.GetNextEntryAsync(cancellationToken: cancellationToken).ConfigureAwait(false) is { } entry)
        {
            if (string.IsNullOrEmpty(entry.Name))
            {
                continue;
            }

            var fullPath = Path.GetFullPath(Path.Combine(destinationPath, entry.Name));

            // Guard against path traversal attacks (e.g., entries containing ".." segments)
            if (!fullPath.StartsWith(normalizedDestination + Path.DirectorySeparatorChar, StringComparison.Ordinal) &&
                !fullPath.Equals(normalizedDestination, StringComparison.Ordinal))
            {
                throw new InvalidOperationException($"Tar entry '{entry.Name}' would extract outside the destination directory.");
            }

            switch (entry.EntryType)
            {
                case TarEntryType.Directory:
                    Directory.CreateDirectory(fullPath);
                    break;

                case TarEntryType.RegularFile:
                    var dir = Path.GetDirectoryName(fullPath);
                    if (dir is not null)
                    {
                        Directory.CreateDirectory(dir);
                    }
                    await entry.ExtractToFileAsync(fullPath, overwrite: true, cancellationToken).ConfigureAwait(false);

                    // Preserve Unix file permissions from tar entry
                    if (!environment.IsWindows() && entry.Mode != default)

View on GitHub (pinned to 25830f84bd)