Skip to content

Commit 0cbdef2

Browse files
authored
PR #519: Restrict path traversal on TarArchive extraction
1 parent 61d3a21 commit 0cbdef2

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.IO;
3+
using System.Numerics;
34
using System.Text;
5+
using ICSharpCode.SharpZipLib.Core;
46

57
namespace ICSharpCode.SharpZipLib.Tar
68
{
@@ -594,13 +596,25 @@ public void ListContents()
594596
/// <param name="destinationDirectory">
595597
/// The destination directory into which to extract.
596598
/// </param>
597-
public void ExtractContents(string destinationDirectory)
599+
public void ExtractContents(string destinationDirectory)
600+
=> ExtractContents(destinationDirectory, false);
601+
602+
/// <summary>
603+
/// Perform the "extract" command and extract the contents of the archive.
604+
/// </summary>
605+
/// <param name="destinationDirectory">
606+
/// The destination directory into which to extract.
607+
/// </param>
608+
/// <param name="allowParentTraversal">Allow parent directory traversal in file paths (e.g. ../file)</param>
609+
public void ExtractContents(string destinationDirectory, bool allowParentTraversal)
598610
{
599611
if (isDisposed)
600612
{
601613
throw new ObjectDisposedException("TarArchive");
602614
}
603615

616+
var fullDistDir = Path.GetFullPath(destinationDirectory);
617+
604618
while (true)
605619
{
606620
TarEntry entry = tarIn.GetNextEntry();
@@ -613,7 +627,7 @@ public void ExtractContents(string destinationDirectory)
613627
if (entry.TarHeader.TypeFlag == TarHeader.LF_LINK || entry.TarHeader.TypeFlag == TarHeader.LF_SYMLINK)
614628
continue;
615629

616-
ExtractEntry(destinationDirectory, entry);
630+
ExtractEntry(fullDistDir, entry, allowParentTraversal);
617631
}
618632
}
619633

@@ -627,7 +641,8 @@ public void ExtractContents(string destinationDirectory)
627641
/// <param name="entry">
628642
/// The TarEntry returned by tarIn.GetNextEntry().
629643
/// </param>
630-
private void ExtractEntry(string destDir, TarEntry entry)
644+
/// <param name="allowParentTraversal">Allow parent directory traversal in file paths (e.g. ../file)</param>
645+
private void ExtractEntry(string destDir, TarEntry entry, bool allowParentTraversal)
631646
{
632647
OnProgressMessageEvent(entry, null);
633648

@@ -644,6 +659,11 @@ private void ExtractEntry(string destDir, TarEntry entry)
644659

645660
string destFile = Path.Combine(destDir, name);
646661

662+
if (!allowParentTraversal && !Path.GetFullPath(destFile).StartsWith(destDir, StringComparison.InvariantCultureIgnoreCase))
663+
{
664+
throw new InvalidNameException("Parent traversal in paths is not allowed");
665+
}
666+
647667
if (entry.IsDirectory)
648668
{
649669
EnsureDirectoryExists(destFile);

0 commit comments

Comments
 (0)