Skip to content

Commit 18486ad

Browse files
committed
1 parent fbb01c4 commit 18486ad

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-7
lines changed

src/Zip/ZipEntry.Extract.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,16 @@ bool IsDoneWithOutputToBaseDir(string baseDir, out string outFileName)
13891389

13901390
// workitem 10639
13911391
outFileName = outFileName.Replace('/', Path.DirectorySeparatorChar);
1392+
1393+
// Resolve any directory traversal sequence and compare the result with the intended base directory
1394+
// where the file or folder will be created.
1395+
// https://gist.github.com/thomas-chauchefoin-bentley-systems/855218959116f870f08857cce2aec731
1396+
var canonicalOutPath = Path.GetFullPath(outFileName);
1397+
var canonicalBaseDir = Path.GetFullPath(baseDir);
1398+
if (!canonicalOutPath.StartsWith(canonicalBaseDir, StringComparison.OrdinalIgnoreCase))
1399+
{
1400+
throw new IOException(string.Format("Extracting {0} would write to {1}, outside of {2}; rejecting.", outFileName, canonicalOutPath, canonicalBaseDir));
1401+
}
13921402

13931403
// check if it is a directory
13941404
if (IsDirectory || FileName.EndsWith("/"))

test/BasicTest.cs

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,52 @@
11
using Xunit;
2+
using Xunit.Abstractions;
23

3-
namespace Ionic.Zip.Tests
4+
namespace Ionic.Zip.Tests;
5+
6+
public class BasicTest
47
{
5-
public class BasicTest
8+
private readonly ITestOutputHelper _output;
9+
10+
public BasicTest(ITestOutputHelper output)
11+
{
12+
_output = output;
13+
}
14+
15+
[Fact]
16+
public void TestCreate()
17+
{
18+
var result = new ZipFile();
19+
Assert.NotNull(result);
20+
}
21+
22+
[Fact]
23+
public void Extract_ZipWithAbsolutePathsOutside()
624
{
7-
[Fact]
8-
public void TestCreate()
25+
Assert.Throws<IOException>(() => Extract_ZipFile("absolute-path-traversal.zip"));
26+
Assert.False(File.Exists(@"C:\Windows\Temp\foo"));
27+
}
28+
29+
private void Extract_ZipFile(string fileName)
30+
{
31+
var sourceDir = Directory.GetCurrentDirectory();
32+
_output.WriteLine("Current Dir: {0}", sourceDir);
33+
34+
var fqFileName = Path.Combine(sourceDir, "zips", fileName);
35+
36+
_output.WriteLine("Reading zip file: '{0}'", fqFileName);
37+
using var zip = ZipFile.Read(fqFileName);
38+
const string extractDir = "extract";
39+
foreach (ZipEntry e in zip)
940
{
10-
var result = new ZipFile();
11-
Assert.NotNull(result);
41+
_output.WriteLine("{1,-22} {2,9} {3,5:F0}% {4,9} {5,3} {6:X8} {0}",
42+
e.FileName,
43+
e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
44+
e.UncompressedSize,
45+
e.CompressionRatio,
46+
e.CompressedSize,
47+
(e.UsesEncryption) ? "Y" : "N",
48+
e.Crc);
49+
e.Extract(extractDir);
1250
}
1351
}
14-
}
52+
}

test/ProDotNetZipNetStandardTest.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,10 @@
2626
<ProjectReference Include="..\src\ProDotNetZipNetStandard.csproj" />
2727
</ItemGroup>
2828

29+
<ItemGroup>
30+
<None Update="zips\absolute-path-traversal.zip">
31+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
32+
</None>
33+
</ItemGroup>
34+
2935
</Project>
143 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)