Skip to content

Commit

Permalink
Adds check that a symlink pointing to a file outside of the destinati…
Browse files Browse the repository at this point in the history
…on is created
  • Loading branch information
ForestEckhardt authored and ryanmoran committed Apr 10, 2021
1 parent 513edf0 commit 1e0c374
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
10 changes: 10 additions & 0 deletions vacation/vacation.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ func (ta TarArchive) Decompress(destination string) error {
}

case tar.TypeSymlink:
err = checkExtractPath(filepath.Join(filepath.Dir(hdr.Name), hdr.Linkname), destination)
if err != nil {
return err
}

err = os.Symlink(hdr.Linkname, path)
if err != nil {
return fmt.Errorf("failed to extract symlink: %s", err)
Expand Down Expand Up @@ -313,6 +318,11 @@ func (z ZipArchive) Decompress(destination string) error {
return err
}

err = checkExtractPath(filepath.Join(filepath.Dir(f.Name), string(content)), destination)
if err != nil {
return err
}

err = os.Symlink(string(content), path)
if err != nil {
return fmt.Errorf("failed to unzip symlink: %w", err)
Expand Down
30 changes: 29 additions & 1 deletion vacation/vacation_tar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,30 @@ func testVacationTar(t *testing.T, context spec.G, it spec.S) {
})
})

context("when it tries to symlink that tries to link to a file outside of the directory", func() {
var zipSlipSymlinkTar vacation.TarArchive

it.Before(func() {
var err error

buffer := bytes.NewBuffer(nil)
tw := tar.NewWriter(buffer)

Expect(tw.WriteHeader(&tar.Header{Name: "symlink", Mode: 0755, Size: int64(0), Typeflag: tar.TypeSymlink, Linkname: filepath.Join("..", "some-file")})).To(Succeed())
_, err = tw.Write([]byte{})
Expect(err).NotTo(HaveOccurred())

Expect(tw.Close()).To(Succeed())

zipSlipSymlinkTar = vacation.NewTarArchive(bytes.NewReader(buffer.Bytes()))
})

it("returns an error", func() {
err := zipSlipSymlinkTar.Decompress(tempDir)
Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("illegal file path %q: the file path does not occur within the destination directory", filepath.Join("..", "some-file")))))
})
})

context("when it tries to decompress a broken symlink", func() {
var brokenSymlinkTar vacation.TarArchive

Expand All @@ -238,12 +262,16 @@ func testVacationTar(t *testing.T, context spec.G, it spec.S) {
buffer := bytes.NewBuffer(nil)
tw := tar.NewWriter(buffer)

Expect(tw.WriteHeader(&tar.Header{Name: "symlink", Mode: 0755, Size: int64(0), Typeflag: tar.TypeSymlink, Linkname: ""})).To(Succeed())
Expect(tw.WriteHeader(&tar.Header{Name: "symlink", Mode: 0755, Size: int64(0), Typeflag: tar.TypeSymlink, Linkname: "some-file"})).To(Succeed())
_, err = tw.Write([]byte{})
Expect(err).NotTo(HaveOccurred())

Expect(tw.Close()).To(Succeed())

// Create a symlink in the target to force the new symlink create to
// fail
Expect(os.Symlink("something", filepath.Join(tempDir, "symlink"))).To(Succeed())

brokenSymlinkTar = vacation.NewTarArchive(bytes.NewReader(buffer.Bytes()))
})

Expand Down
28 changes: 28 additions & 0 deletions vacation/vacation_zip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,34 @@ func testVacationZip(t *testing.T, context spec.G, it spec.S) {
})
})

context("when it tries to symlink that tries to link to a file outside of the directory", func() {
var buffer *bytes.Buffer
it.Before(func() {
var err error
buffer = bytes.NewBuffer(nil)
zw := zip.NewWriter(buffer)

header := &zip.FileHeader{Name: "symlink"}
header.SetMode(0755 | os.ModeSymlink)

symlink, err := zw.CreateHeader(header)
Expect(err).NotTo(HaveOccurred())

_, err = symlink.Write([]byte(filepath.Join("..", "some-file")))
Expect(err).NotTo(HaveOccurred())

Expect(zw.Close()).To(Succeed())

})

it("returns an error", func() {
readyArchive := vacation.NewZipArchive(buffer)

err := readyArchive.Decompress(tempDir)
Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("illegal file path %q: the file path does not occur within the destination directory", filepath.Join("..", "some-file")))))
})
})

context("when it fails to unzip a symlink", func() {
var buffer *bytes.Buffer
it.Before(func() {
Expand Down

0 comments on commit 1e0c374

Please sign in to comment.