TechnitiumSoftware/DnsServer · error · IOException
Extracting Zip entry would have resulted in a file outside t
Error message
Extracting Zip entry would have resulted in a file outside the specified destination directory.
What it means
Thrown during both install and update extraction when a ZipArchiveEntry's full target path would land outside the application folder. This is the classic 'zip-slip' mitigation (CVE pattern): every entry is canonicalized and checked against the destination prefix.
Source
Thrown at DnsServerCore/Dns/Applications/DnsApplicationManager.cs:436
string applicationFolder = Path.Combine(_appsPath, applicationName);
//keep a copy of the zip file in the application folder for transferring to other nodes
await using (FileStream zipCopyStream = new FileStream(Path.Combine(applicationFolder, applicationName + ".zip"), FileMode.Create, FileAccess.ReadWrite))
{
await appZipStream.CopyToAsync(zipCopyStream);
zipCopyStream.Position = 0;
await using (ZipArchive appZip = new ZipArchive(zipCopyStream, ZipArchiveMode.Read, false, Encoding.UTF8))
{
UnloadApplication(applicationName);
foreach (ZipArchiveEntry entry in appZip.Entries)
{
string filePath = Path.GetFullPath(Path.Combine(applicationFolder, entry.FullName));
if (!filePath.StartsWith(applicationFolder + Path.DirectorySeparatorChar))
throw new IOException("Extracting Zip entry would have resulted in a file outside the specified destination directory.");
if ((entry.Name == "dnsApp.config") && File.Exists(filePath))
continue; //avoid overwriting existing config file
if ((entry.Length == 0) && (entry.Name.Length == 0) && entry.FullName.EndsWith('/'))
{
//directory entry
Directory.CreateDirectory(filePath);
}
else
{
//file entry
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
await entry.ExtractToFileAsync(filePath, true);
}
}
View on GitHub (pinned to d0484b6c1e)
Solutions
- Inspect the zip's entry list before install and reject entries containing '..' or rooted paths.
- Re-package the app so all entries are relative to the application root with no parent traversal.
- Only install apps from trusted authors; verify the zip's directory structure after extraction tooling.
- If you control packaging, build with a tool that emits only relative, in-root entries (e.g. zip from inside the folder).
Example fix
// before
using var zip = new ZipArchive(stream, ZipArchiveMode.Read);
foreach (var e in zip.Entries) { /* trust entries */ }
// after
using var zip = new ZipArchive(stream, ZipArchiveMode.Read);
if (zip.Entries.Any(e => e.FullName.Contains("..") || Path.IsPathRooted(e.FullName)))
throw new InvalidOperationException("Refusing zip with traversal/rooted entries"); Defensive patterns
Strategy: validation
Validate before calling
bool ZipIsSafe(Stream s)
{
using var zip = new ZipArchive(s, ZipArchiveMode.Read, leaveOpen: true);
return zip.Entries.All(e => !e.FullName.Contains("..") && !Path.IsPathRooted(e.FullName));
} Type guard
static bool IsSafeZipEntry(string fullName) =>
!fullName.Contains("..") && !Path.IsPathRooted(fullName); Try / catch
try { await mgr.InstallApplicationAsync(name, zip); }
catch (IOException ex) when (ex.Message.Contains("outside the specified destination")) { log.Warn($"Rejected traversal zip for {name}"); } Prevention
- Pre-scan zips for '..' or rooted entries before install.
- Only install apps from trusted sources.
- Build app packages from inside the app root so all entries are relative.
When it happens
Trigger: A zip containing an entry whose FullName uses ../ to climb out of applicationFolder (e.g. ../../etc/passwd), or an entry with an absolute/rooted path that resolves outside. Triggered by a malicious or poorly authored app package.
Common situations: Side-loaded third-party app zip; zip produced on Windows with backslash paths extracted on Linux (or vice versa) where separator normalization causes a mismatch; deliberately packaged app that escapes its dir.
Related errors
- The application name is invalid: {applicationName}
- Cluster node URL must use HTTPS scheme.
- The application name contains an invalid character: {invalid
- DNS application already exists: {applicationName}
- Zone transfer TSIG key names cannot have more than 255 entri
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/232a9c393b63d405.
Report an issue: GitHub.