Skip to content

Commit

Permalink
Patch malicious tarballs directory traversal vuln (#7057)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdoherty4 authored Nov 18, 2023
1 parent f520284 commit 44d3582
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
8 changes: 8 additions & 0 deletions pkg/tar/untar.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package tar

import (
"archive/tar"
"fmt"
"io"
"os"
"strings"
)

func UntarFile(tarFile, dstFolder string) error {

Check warning on line 11 in pkg/tar/untar.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported function UntarFile should have comment or be unexported (revive)
Expand Down Expand Up @@ -32,6 +34,12 @@ func Untar(source io.Reader, router Router) error {
continue
}

// Prevent malicous directory traversals.
// https://cwe.mitre.org/data/definitions/22.html
if strings.Contains(header.Name, "..") {
return fmt.Errorf("file in tarball contains a directory traversal component (..): %v", header.Name)
}

info := header.FileInfo()
if info.IsDir() {
if err = os.MkdirAll(path, info.Mode()); err != nil {
Expand Down
44 changes: 44 additions & 0 deletions pkg/tar/untar_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package tar_test

import (
stdtar "archive/tar"
"bytes"
"io"
"io/fs"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -30,3 +34,43 @@ func TestUntarFile(t *testing.T) {
g.Expect(filepath.Join(untarFolder, "dummy3")).To(BeADirectory())
g.Expect(filepath.Join(untarFolder, "dummy3", "dummy4")).To(BeARegularFile())
}

func TestUntarFile_DirTraversalComponents(t *testing.T) {
// This test ensures Untar fails when a tarball contains paths with directory traversal
// components. It addresses https://cwe.mitre.org/data/definitions/22.html.
g := NewWithT(t)

dir := t.TempDir()
tarPath := filepath.Join(dir, "test")
fh, err := os.Create(tarPath)
g.Expect(err).To(Succeed())

createArbitraryTarball(t, fh)

g.Expect(tar.UntarFile(tarPath, dir)).ToNot(Succeed())
}

func createArbitraryTarball(t *testing.T, w io.Writer) {
t.Helper()

tb := stdtar.NewWriter(w)

data := bytes.NewBufferString("Hello, world!")
header := stdtar.Header{
Name: "../foobar",
Mode: int64(fs.ModePerm),
Typeflag: stdtar.TypeReg,
Size: int64(data.Len()),
}

if err := tb.WriteHeader(&header); err != nil {
t.Fatal(err)
}

_, err := io.Copy(tb, data)
if err != nil {
t.Fatal(err)
}

tb.Close()
}

0 comments on commit 44d3582

Please sign in to comment.