SubtitleEdit/subtitleedit · error · InvalidDataException
Archive entry is outside the extraction folder: {reader.Entr
Error message
Archive entry is outside the extraction folder: {reader.Entry.Key} What it means
InvalidDataException from the second Zip-Slip guard: after GetFullPath, the entry resolves to a path whose relative form equals '..' or starts with '..' (+separator) or is rooted, meaning it escapes targetRoot.
Source
Thrown at src/ui/Logic/SevenZipExtractor/Unpacker.cs:431
entryFullName = entryFullName.TrimStart(Path.DirectorySeparatorChar);
if (string.IsNullOrEmpty(entryFullName))
{
if (reader.Entry.IsDirectory)
{
Directory.CreateDirectory(dir);
continue;
}
throw new InvalidDataException("Archive contains an empty file entry name.");
}
var fullFileName = Path.GetFullPath(Path.Combine(targetRoot, entryFullName));
var relativePath = Path.GetRelativePath(targetRoot, fullFileName);
if (relativePath.Equals("..", StringComparison.Ordinal) ||
relativePath.StartsWith(".." + Path.DirectorySeparatorChar, StringComparison.Ordinal) ||
Path.IsPathRooted(relativePath))
{
throw new InvalidDataException($"Archive entry is outside the extraction folder: {reader.Entry.Key}");
}
if (reader.Entry.IsDirectory)
{
if (!Directory.Exists(fullFileName))
{
Directory.CreateDirectory(fullFileName);
}
continue;
}
var fullPath = Path.GetDirectoryName(fullFileName);
if (fullPath == null)
{
continue;
}
View on GitHub (pinned to 17a9f07487)
Solutions
- Treat the archive as untrusted and reject/quarantine it; this guard is load-bearing for security.
- Rebuild the archive with safe, in-tree relative paths.
- Verify publisher and hash before extraction.
Example fix
// before
Unpacker.ExtractArchive(archivePath, dest);
// after
try { Unpacker.ExtractArchive(archivePath, dest); }
catch (InvalidDataException ex) when (ex.Message.Contains("outside the extraction folder"))
{
Quarantine(archivePath);
logger.LogWarning("Rejected traversal attempt in {Archive}", archivePath);
} Defensive patterns
Strategy: validation
Validate before calling
foreach (var entry in ListEntries(archive))
{
var full = Path.GetFullPath(Path.Combine(dest, entry.Key));
var rel = Path.GetRelativePath(dest, full);
if (rel.Equals("..") || rel.StartsWith(".." + Path.DirectorySeparatorChar) || Path.IsPathRooted(rel))
{
Quarantine(archive);
throw new InvalidDataException($"Refusing traversal entry {entry.Key}");
}
} Try / catch
try { Unpacker.ExtractArchive(archive, dest); }
catch (InvalidDataException ex) when (ex.Message.Contains("outside the extraction folder"))
{
Quarantine(archive);
logger.LogWarning("Rejected traversal archive {Archive}", archive);
} Prevention
- Only extract trusted, publisher-verified archives.
- Never suppress the traversal guard.
- Pre-scan entries for '..' escape sequences.
When it happens
Trigger: Archive entries like '../evil.dll', '..\\..\\system32\\x', or nested traversal sequences that resolve above targetRoot despite not being absolute.
Common situations: Malicious archives designed to escape the extraction folder, or archives built from a parent directory.
Related errors
- Archive entry is rooted outside the extraction folder: {read
- Archive contains an empty file entry name.
- Too many bytes for CCData!
- Color '{colorName}' not found in SKColors.
- End of file reached before expected
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/939ae5fcd2be216f.
Report an issue: GitHub.