Skip to content

Commit b5f0a73

Browse files
committed
fix: mholt#65#issuecomment-395988244 - zip slip by symlink
1 parent f1afa5e commit b5f0a73

4 files changed

Lines changed: 33 additions & 8 deletions

File tree

archiver.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"path/filepath"
99
"runtime"
1010
"strings"
11+
12+
"github.com/cyphar/filepath-securejoin"
1113
)
1214

1315
// Archiver represent a archive format
@@ -111,8 +113,12 @@ func sanitizeExtractPath(filePath string, destination string) error {
111113
// to avoid zip slip (writing outside of the destination), we resolve
112114
// the target path, and make sure it's nested in the intended
113115
// destination, or bail otherwise.
114-
destpath := filepath.Join(destination, filePath)
115-
if !strings.HasPrefix(destpath, destination) {
116+
destpath, err := securejoin.SecureJoin(destination, filePath)
117+
if err != nil {
118+
return fmt.Errorf(
119+
"%s: error calculating destination path", filePath)
120+
}
121+
if !strings.HasPrefix(destpath, destination+string(os.PathSeparator)) {
116122
return fmt.Errorf("%s: illegal file path", filePath)
117123
}
118124
return nil

rar.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"path/filepath"
99
"strings"
1010

11+
"github.com/cyphar/filepath-securejoin"
1112
"github.com/nwaples/rardecode"
1213
)
1314

@@ -77,8 +78,10 @@ func (rarFormat) Read(input io.Reader, destination string) error {
7778
return err
7879
}
7980

80-
destpath := filepath.Join(destination, header.Name)
81-
81+
destpath, err := securejoin.SecureJoin(destination, header.Name)
82+
if err != nil {
83+
return err
84+
}
8285
if header.IsDir {
8386
err = mkdir(destpath)
8487
if err != nil {

tar.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"path/filepath"
1010
"strconv"
1111
"strings"
12+
13+
"github.com/cyphar/filepath-securejoin"
1214
)
1315

1416
// Tar is for Tar format
@@ -224,7 +226,10 @@ func untarFile(tr *tar.Reader, header *tar.Header, destination string) error {
224226
return err
225227
}
226228

227-
destpath := filepath.Join(destination, header.Name)
229+
destpath, err := securejoin.SecureJoin(destination, header.Name)
230+
if err != nil {
231+
return err
232+
}
228233

229234
switch header.Typeflag {
230235
case tar.TypeDir:
@@ -234,7 +239,12 @@ func untarFile(tr *tar.Reader, header *tar.Header, destination string) error {
234239
case tar.TypeSymlink:
235240
return writeNewSymbolicLink(destpath, header.Linkname)
236241
case tar.TypeLink:
237-
return writeNewHardLink(destpath, filepath.Join(destination, header.Linkname))
242+
linkpath, err := securejoin.SecureJoin(destination, header.Linkname)
243+
if err != nil {
244+
return err
245+
}
246+
return writeNewHardLink(
247+
destpath, linkpath)
238248
default:
239249
return fmt.Errorf("%s: unknown type flag: %c", header.Name, header.Typeflag)
240250
}

zip.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
"path"
1313
"path/filepath"
1414
"strings"
15+
16+
"github.com/cyphar/filepath-securejoin"
1517
)
1618

1719
// Zip is for Zip format
@@ -192,8 +194,12 @@ func unzipFile(zf *zip.File, destination string) error {
192194
return err
193195
}
194196

197+
destpath, err := securejoin.SecureJoin(destination, zf.Name)
198+
if err != nil {
199+
return fmt.Errorf("%s: calculating file path: %v", zf.Name, err)
200+
}
195201
if strings.HasSuffix(zf.Name, "/") {
196-
return mkdir(filepath.Join(destination, zf.Name))
202+
return mkdir(destpath)
197203
}
198204

199205
rc, err := zf.Open()
@@ -202,7 +208,7 @@ func unzipFile(zf *zip.File, destination string) error {
202208
}
203209
defer rc.Close()
204210

205-
return writeNewFile(filepath.Join(destination, zf.Name), rc, zf.FileInfo().Mode())
211+
return writeNewFile(destpath, rc, zf.FileInfo().Mode())
206212
}
207213

208214
// compressedFormats is a (non-exhaustive) set of lowercased

0 commit comments

Comments
 (0)