Skip to content

Commit

Permalink
Potential fix for zipslip
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanuber committed Dec 1, 2020
1 parent dbc66eb commit 764785b
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 18 deletions.
12 changes: 12 additions & 0 deletions slug.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,18 @@ func Unpack(r io.Reader, dst string) error {
header.Name, header.Linkname)
}

// Ensure the destination is not through any symlinks. This prevents
// the zipslip vulnerability.
if fi, err := os.Lstat(dir); !os.IsNotExist(err) {
if err != nil {
return fmt.Errorf("Failed to stat %q: %v", dir, err)
}
if fi.Mode()&os.ModeSymlink != 0 {
return fmt.Errorf("Cannot extract %q through symlink",
header.Name)
}
}

// Create the symlink.
if err := os.Symlink(header.Linkname, path); err != nil {
return fmt.Errorf("Failed creating symlink (%q -> %q): %v",
Expand Down
72 changes: 54 additions & 18 deletions slug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,25 +391,59 @@ func TestUnpackErrorOnUnhandledType(t *testing.T) {
}

func TestUnpackMaliciousSymlinks(t *testing.T) {
tcases := []struct {
desc string
type link struct {
path string
target string
err string
}

tcases := []struct {
desc string
links []link
err string
}{
{
desc: "symlink with absolute path",
target: "/etc/shadow",
err: "has absolute target",
desc: "symlink with absolute path",
links: []link{
{
path: "l",
target: "/etc/shadow",
},
},
err: "has absolute target",
},
{
desc: "symlink with external target",
target: "../../../../../etc/shadow",
err: "has external target",
desc: "symlink with external target",
links: []link{
{
path: "l",
target: "../../../../../etc/shadow",
},
},
err: "has external target",
},
{
desc: "symlink with nested external target",
target: "foo/bar/baz/../../../../../../../../etc/shadow",
err: "has external target",
desc: "symlink with nested external target",
links: []link{
{
path: "l",
target: "foo/bar/baz/../../../../../../../../etc/shadow",
},
},
err: "has external target",
},
{
desc: "zipslip vulnerability",
links: []link{
{
path: "subdir/parent",
target: "..",
},
{
path: "subdir/parent/escapes",
target: "..",
},
},
err: `Cannot extract "subdir/parent/escapes" through symlink`,
},
}

Expand All @@ -435,14 +469,16 @@ func TestUnpackMaliciousSymlinks(t *testing.T) {
// Tar the file contents
tarW := tar.NewWriter(gzipW)

var hdr tar.Header
for _, link := range tc.links {
var hdr tar.Header

hdr.Typeflag = tar.TypeSymlink
hdr.Name = "l"
hdr.Size = int64(0)
hdr.Linkname = tc.target
hdr.Typeflag = tar.TypeSymlink
hdr.Name = link.path
hdr.Size = int64(0)
hdr.Linkname = link.target

tarW.WriteHeader(&hdr)
tarW.WriteHeader(&hdr)
}

tarW.Close()
gzipW.Close()
Expand Down

0 comments on commit 764785b

Please sign in to comment.