Skip to content

Commit

Permalink
Refactored the path resolution to use securejoin
Browse files Browse the repository at this point in the history
[#157757626]

Signed-off-by: Edwin Xie <exie@pivotal.io>
  • Loading branch information
sjolicoeur authored and flawedmatrix committed May 23, 2018
1 parent 7291196 commit 09b5706
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 5 deletions.
97 changes: 97 additions & 0 deletions extractor/extractor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ var _ = Describe("Extractor", func() {
})

It("extracts the ZIP's files, generating directories, and honoring file permissions and symlinks", extractionTest)

Context("with a bad zip archive", func() {
BeforeEach(func() {
test_helper.CreateZipArchive(extractionSrc, []test_helper.ArchiveFile{
{
Name: "../some-file",
Body: "file-in-bad-dir-contents",
},
})
})

It("returns an error", func() {
subdir := filepath.Join(extractionDest, "subdir")
Expect(os.Mkdir(subdir, 0777)).To(Succeed())
err := extractor.Extract(extractionSrc, subdir)
Expect(err).To(HaveOccurred())
})
})
})

Context("when 'unzip' is not in the PATH", func() {
Expand All @@ -138,6 +156,27 @@ var _ = Describe("Extractor", func() {
})

It("extracts the ZIP's files, generating directories, and honoring file permissions and symlinks", extractionTest)

Context("with a bad zip archive", func() {
BeforeEach(func() {
test_helper.CreateZipArchive(extractionSrc, []test_helper.ArchiveFile{
{
Name: "../some-file",
Body: "file-in-bad-dir-contents",
},
})
})

It("does not insecurely extract the file outside of the provided destination", func() {
subdir := filepath.Join(extractionDest, "subdir")
Expect(os.Mkdir(subdir, 0777)).To(Succeed())
err := extractor.Extract(extractionSrc, subdir)
Expect(err).NotTo(HaveOccurred())

Expect(filepath.Join(extractionDest, "some-file")).NotTo(BeAnExistingFile())
Expect(filepath.Join(subdir, "some-file")).To(BeAnExistingFile())
})
})
})
})

Expand All @@ -153,6 +192,24 @@ var _ = Describe("Extractor", func() {
})

It("extracts the TGZ's files, generating directories, and honoring file permissions and symlinks", extractionTest)

Context("with a bad tgz archive", func() {
BeforeEach(func() {
test_helper.CreateTarGZArchive(extractionSrc, []test_helper.ArchiveFile{
{
Name: "../some-file",
Body: "file-in-bad-dir-contents",
},
})
})

It("returns an error", func() {
subdir := filepath.Join(extractionDest, "subdir")
Expect(os.Mkdir(subdir, 0777)).To(Succeed())
err := extractor.Extract(extractionSrc, subdir)
Expect(err).To(HaveOccurred())
})
})
})

Context("when 'tar' is not in the PATH", func() {
Expand All @@ -171,6 +228,26 @@ var _ = Describe("Extractor", func() {
})

It("extracts the TGZ's files, generating directories, and honoring file permissions and symlinks", extractionTest)

Context("with a bad tgz archive", func() {
BeforeEach(func() {
test_helper.CreateTarGZArchive(extractionSrc, []test_helper.ArchiveFile{
{
Name: "../some-file",
Body: "file-in-bad-dir-contents",
},
})
})

It("does not insecurely extract the file outside of the provided destination", func() {
subdir := filepath.Join(extractionDest, "subdir")
Expect(os.Mkdir(subdir, 0777)).To(Succeed())
err := extractor.Extract(extractionSrc, subdir)
Expect(err).NotTo(HaveOccurred())
Expect(filepath.Join(extractionDest, "some-file")).NotTo(BeAnExistingFile())
Expect(filepath.Join(subdir, "some-file")).To(BeAnExistingFile())
})
})
})
})

Expand All @@ -181,5 +258,25 @@ var _ = Describe("Extractor", func() {
})

It("extracts the TAR's files, generating directories, and honoring file permissions and symlinks", extractionTest)

Context("with a bad tar archive", func() {
BeforeEach(func() {
test_helper.CreateTarArchive(extractionSrc, []test_helper.ArchiveFile{
{
Name: "../some-file",
Body: "file-in-bad-dir-contents",
},
})
})

It("does not insecurely extract the file outside of the provided destination", func() {
subdir := filepath.Join(extractionDest, "subdir")
Expect(os.Mkdir(subdir, 0777)).To(Succeed())
err := extractor.Extract(extractionSrc, subdir)
Expect(err).NotTo(HaveOccurred())
Expect(filepath.Join(extractionDest, "some-file")).NotTo(BeAnExistingFile())
Expect(filepath.Join(subdir, "some-file")).To(BeAnExistingFile())
})
})
})
})
9 changes: 7 additions & 2 deletions extractor/tgz_extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"os"
"os/exec"
"path/filepath"

securejoin "github.com/cyphar/filepath-securejoin"
)

type tgzExtractor struct{}
Expand Down Expand Up @@ -87,14 +89,17 @@ func extractTarArchive(tarReader *tar.Reader, dest string) error {
}

func extractTarArchiveFile(header *tar.Header, dest string, input io.Reader) error {
filePath := filepath.Join(dest, header.Name)
filePath, err := securejoin.SecureJoin(dest, header.Name)
if err != nil {
return err
}
fileInfo := header.FileInfo()

if fileInfo.IsDir() {
return os.MkdirAll(filePath, fileInfo.Mode())
}

err := os.MkdirAll(filepath.Dir(filePath), 0755)
err = os.MkdirAll(filepath.Dir(filePath), 0755)
if err != nil {
return err
}
Expand Down
8 changes: 5 additions & 3 deletions extractor/zip_extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"os"
"os/exec"
"path/filepath"

securejoin "github.com/cyphar/filepath-securejoin"
)

type zipExtractor struct{}
Expand Down Expand Up @@ -77,16 +79,16 @@ func extractZip(src, dest string) error {
}

func extractZipArchiveFile(file *zip.File, dest string, input io.Reader) error {
filePath := filepath.Join(dest, file.Name)
filePath, err := securejoin.SecureJoin(dest, file.Name)
fileInfo := file.FileInfo()

if fileInfo.IsDir() {
err := os.MkdirAll(filePath, fileInfo.Mode())
err = os.MkdirAll(filePath, fileInfo.Mode())
if err != nil {
return err
}
} else {
err := os.MkdirAll(filepath.Dir(filePath), 0755)
err = os.MkdirAll(filepath.Dir(filePath), 0755)
if err != nil {
return err
}
Expand Down

0 comments on commit 09b5706

Please sign in to comment.