Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions archiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
)

// Archiver represent a archive format
Expand Down Expand Up @@ -105,3 +106,14 @@ func mkdir(dirPath string) error {
}
return nil
}

func sanitizeExtractPath(filePath string, destination string) error {
// to avoid zip slip (writing outside of the destination), we resolve
// the target path, and make sure it's nested in the intended
// destination, or bail otherwise.
destpath := filepath.Join(destination, filePath)
if !strings.HasPrefix(destpath, destination) {
return fmt.Errorf("%s: illegal file path", filePath)
}
return nil
}
5 changes: 4 additions & 1 deletion cmd/archiver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ func main() {
}
err = ff.Make(filename, os.Args[3:])
case "open":
dest := ""
dest, osErr := os.Getwd()
if osErr != nil {
fatal(err)
}
if len(os.Args) == 4 {
dest = os.Args[3]
} else if len(os.Args) > 4 {
Expand Down
13 changes: 10 additions & 3 deletions rar.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,15 @@ func (rarFormat) Read(input io.Reader, destination string) error {
return err
}

err = sanitizeExtractPath(header.Name, destination)
if err != nil {
return err
}

destpath := filepath.Join(destination, header.Name)

if header.IsDir {
err = mkdir(filepath.Join(destination, header.Name))
err = mkdir(destpath)
if err != nil {
return err
}
Expand All @@ -82,12 +89,12 @@ func (rarFormat) Read(input io.Reader, destination string) error {

// if files come before their containing folders, then we must
// create their folders before writing the file
err = mkdir(filepath.Dir(filepath.Join(destination, header.Name)))
err = mkdir(filepath.Dir(destpath))
if err != nil {
return err
}

err = writeNewFile(filepath.Join(destination, header.Name), rr, header.Mode())
err = writeNewFile(destpath, rr, header.Mode())
if err != nil {
return err
}
Expand Down
15 changes: 11 additions & 4 deletions tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,22 @@ func untar(tr *tar.Reader, destination string) error {

// untarFile untars a single file from tr with header header into destination.
func untarFile(tr *tar.Reader, header *tar.Header, destination string) error {
err := sanitizeExtractPath(header.Name, destination)
if err != nil {
return err
}

destpath := filepath.Join(destination, header.Name)

switch header.Typeflag {
case tar.TypeDir:
return mkdir(filepath.Join(destination, header.Name))
return mkdir(destpath)
case tar.TypeReg, tar.TypeRegA, tar.TypeChar, tar.TypeBlock, tar.TypeFifo:
return writeNewFile(filepath.Join(destination, header.Name), tr, header.FileInfo().Mode())
return writeNewFile(destpath, tr, header.FileInfo().Mode())
case tar.TypeSymlink:
return writeNewSymbolicLink(filepath.Join(destination, header.Name), header.Linkname)
return writeNewSymbolicLink(destpath, header.Linkname)
case tar.TypeLink:
return writeNewHardLink(filepath.Join(destination, header.Name), filepath.Join(destination, header.Linkname))
return writeNewHardLink(destpath, filepath.Join(destination, header.Linkname))
default:
return fmt.Errorf("%s: unknown type flag: %c", header.Name, header.Typeflag)
}
Expand Down
5 changes: 5 additions & 0 deletions zip.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ func unzipAll(r *zip.Reader, destination string) error {
}

func unzipFile(zf *zip.File, destination string) error {
err := sanitizeExtractPath(zf.Name, destination)
if err != nil {
return err
}

if strings.HasSuffix(zf.Name, "/") {
return mkdir(filepath.Join(destination, zf.Name))
}
Expand Down