microsoft/aspire · error · InvalidOperationException
Symlink ' ' targets ' ' which resolves outside the…
Error message
Symlink '{entry.Name}' targets '{entry.LinkName}' which resolves outside the destination directory. What it means
During tar.gz extraction, symlinks are validated by resolving their LinkName relative to the entry's directory; if the resolved target lies outside the destination directory the extraction is aborted with InvalidOperationException. This prevents symlink-based escapes from the extraction root.
Solutions
- Re-download the archive from a trusted source.
- Inspect symlinks (tar -tvzf) and repack so link targets resolve inside the archive root.
- If you control packaging, avoid emitting symlinks with targets outside the staged directory.
Example fix
// before // entry "link" -> "../../../etc/passwd" // after // repack: entry "link" -> "./data/file" (resolves inside destination)
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);
while (await tar.GetNextEntryAsync() is { } e)
{
if (e.EntryType == TarEntryType.SymbolicLink)
{
var resolved = Path.GetFullPath(Path.Combine(destinationPath, e.LinkName));
if (!resolved.StartsWith(Path.GetFullPath(destinationPath) + Path.DirectorySeparatorChar, StringComparison.Ordinal)) throw new InvalidOperationException($"Unsafe symlink: {e.Name} -> {e.LinkName}");
}
} Try / catch
try { await ArchiveHelper.ExtractAsync(tgzPath, dest, env, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Symlink")) { // reject archive with escaping symlink
} Prevention
- Prefer archives without symlinks when packaging.
- Verify archive provenance and checksums.
- Pre-scan symlink entries and resolve their targets before extraction.
When it happens
Trigger: Extracting a tar.gz containing a symlink whose LinkName (e.g. '../../../outside' or an absolute path) resolves outside the destination directory.
Common situations: Malicious archives that pair in-bounds entries with out-of-bounds symlinks; archives copied from filesystem layouts where relative link targets pointed elsewhere; corrupted archives.
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
- Tar entry ' ' would extract outside the destination…
- Aspire skills archive entry
- Aspire skills GitHub release asset
- Symlink ' ' targets ' ' which resolves outside the…
- Tar entry ' ' would extract outside the destination…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/2aefac1528ce5e9f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Utils/ArchiveHelper.cs:126
// Preserve Unix file permissions from tar entry
if (!environment.IsWindows() && entry.Mode != default)
{
File.SetUnixFileMode(fullPath, (UnixFileMode)entry.Mode);
}
break;
case TarEntryType.SymbolicLink:
if (string.IsNullOrEmpty(entry.LinkName))
{
continue;
}
// Validate symlink target stays within the extraction directory
var linkTarget = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(fullPath)!, entry.LinkName));
if (!linkTarget.StartsWith(normalizedDestination + Path.DirectorySeparatorChar, StringComparison.Ordinal) &&
!linkTarget.Equals(normalizedDestination, StringComparison.Ordinal))
{
throw new InvalidOperationException($"Symlink '{entry.Name}' targets '{entry.LinkName}' which resolves outside the destination directory.");
}
var linkDir = Path.GetDirectoryName(fullPath);
if (linkDir is not null)
{
Directory.CreateDirectory(linkDir);
}
if (File.Exists(fullPath))
{
File.Delete(fullPath);
}
File.CreateSymbolicLink(fullPath, entry.LinkName);
break;
}
}
}
}
View on GitHub (pinned to 25830f84bd)