@@ -21,6 +21,7 @@ import (
2121 "fmt"
2222 "io"
2323 "os"
24+ pathpkg "path"
2425 "path/filepath"
2526 "strings"
2627
@@ -50,7 +51,10 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
5051 if err != nil {
5152 return errors .Wrap (err , "Error getting next tar header" )
5253 }
53- target := filepath .Clean (filepath .Join (path , header .Name ))
54+ target , err := ResolvePathInRoot (path , header .Name , false )
55+ if err != nil {
56+ return errors .Wrap (err , "resolving tar entry path" )
57+ }
5458 // Make sure the target isn't part of the whitelist
5559 if checkWhitelist (target , whitelist ) {
5660 continue
@@ -60,7 +64,7 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
6064
6165 // if its a dir and it doesn't exist create it
6266 case tar .TypeDir :
63- if _ , err := os .Stat (target ); os .IsNotExist (err ) {
67+ if _ , err := os .Lstat (target ); os .IsNotExist (err ) {
6468 if mode .Perm ()& (1 << (uint (7 ))) == 0 {
6569 logrus .Debugf ("Write permission bit not set on %s by default; setting manually" , target )
6670 originalMode := mode
@@ -93,7 +97,7 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
9397 }
9498 // It's possible we end up creating files that can't be overwritten based on their permissions.
9599 // Explicitly delete an existing file before continuing.
96- if _ , err := os .Stat (target ); ! os .IsNotExist (err ) {
100+ if _ , err := os .Lstat (target ); ! os .IsNotExist (err ) {
97101 logrus .Debugf ("Removing %s for overwrite" , target )
98102 if err := os .Remove (target ); err != nil {
99103 logrus .Errorf ("error removing file %s" , target )
@@ -118,9 +122,12 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
118122 }
119123 currFile .Close ()
120124 case tar .TypeSymlink :
125+ if _ , err := ResolvePathInRoot (path , tarLinkTarget (header .Name , header .Linkname ), true ); err != nil {
126+ return errors .Wrap (err , "resolving tar symlink path" )
127+ }
121128 // It's possible we end up creating files that can't be overwritten based on their permissions.
122129 // Explicitly delete an existing file before continuing.
123- if _ , err := os .Stat (target ); ! os .IsNotExist (err ) {
130+ if _ , err := os .Lstat (target ); ! os .IsNotExist (err ) {
124131 logrus .Debugf ("Removing %s to create symlink" , target )
125132 if err := os .RemoveAll (target ); err != nil {
126133 logrus .Debugf ("Unable to remove %s: %s" , target , err )
@@ -131,7 +138,10 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
131138 logrus .Errorf ("Failed to create symlink between %s and %s: %s" , header .Linkname , target , err )
132139 }
133140 case tar .TypeLink :
134- linkname := filepath .Clean (filepath .Join (path , header .Linkname ))
141+ linkname , err := ResolvePathInRoot (path , header .Linkname , true )
142+ if err != nil {
143+ return errors .Wrap (err , "resolving tar hard link path" )
144+ }
135145 // Check if the linkname already exists
136146 if _ , err := os .Stat (linkname ); ! os .IsNotExist (err ) {
137147 // If it exists, create the hard link
@@ -168,6 +178,13 @@ func unpackTar(tr *tar.Reader, path string, whitelist []string) error {
168178 return nil
169179}
170180
181+ func tarLinkTarget (name , linkname string ) string {
182+ if pathpkg .IsAbs (filepath .ToSlash (linkname )) {
183+ return linkname
184+ }
185+ return pathpkg .Join (pathpkg .Dir (filepath .ToSlash (name )), filepath .ToSlash (linkname ))
186+ }
187+
171188func resolveHardlink (linkname , target string ) error {
172189 if err := os .Link (linkname , target ); err != nil {
173190 return err
0 commit comments