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
BundleService throws this while extracting a bundle archive when a symlink entry would resolve to a path outside the destination directory. It is a zip-slip style path traversal guard: after resolving the link target relative to the link's directory, the full path must remain inside the normalized destination. Throwing prevents an attacker-crafted bundle from writing files outside the extraction root.
Solutions
- Fix the bundle so symlink targets are relative and resolve inside the destination directory
- Inspect the bundle entries with an archive tool to find the offending symlink (entry.Name -> entry.LinkName)
- If you own bundle creation, rewrite absolute/parent-escaping link targets to relative paths within the archive
Example fix
// before (in bundle manifest): symlink target escaping root entry.LinkName = "../../../../etc/passwd" // after: relative target inside destination entry.LinkName = "../lib/foo.so"
Defensive patterns
Strategy: validation
Validate before calling
var resolved = Path.GetFullPath(Path.Combine(dir, linkName));
if (!resolved.StartsWith(destRoot + Path.DirectorySeparatorChar) && resolved != destRoot)
throw new InvalidOperationException("Symlink escapes destination directory"); Prevention
- Only extract bundles from trusted sources
- Audit symlink entries in archives before extraction
- Keep link targets relative and inside the archive root
When it happens
Trigger: Extracting a bundle containing a symlink whose LinkName is absolute, or contains '..' segments, or otherwise resolves (via Path.GetFullPath) to a path outside normalizedDestination.
Common situations: Using a hand-edited or third-party bundle archive; bundles repacked with symlinks pointing to shared libraries outside the extraction dir; bundles moved between machines where relative link targets resolve differently.
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
- Aspire skills archive entry
- Aspire skills archive entry
- Tar entry ' ' would extract outside the destination…
- Aspire skills bundle path
- Symlink ' ' targets ' ' which resolves outside the…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/a1d6bd2e3e281965.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Bundles/BundleService.cs:932
// Preserve Unix file permissions from tar entry (e.g., execute bit)
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)