44 "archive/tar"
55 "archive/zip"
66 "errors"
7+ "fmt"
78 "io"
89 "log"
910 "os"
@@ -54,8 +55,10 @@ func unzipFile(file *zip.File, target string) error {
5455 if err != nil {
5556 return err
5657 }
57- // #nosec G305
58- name := path .Join (target , file .Name )
58+ name , err := sanitizeArchivePath (target , file .Name )
59+ if err != nil {
60+ return err
61+ }
5962 _ = os .MkdirAll (path .Dir (name ), os .ModeDir )
6063 create , err := os .Create (name )
6164 if err != nil {
@@ -66,6 +69,16 @@ func unzipFile(file *zip.File, target string) error {
6669 return err
6770}
6871
72+ // sanitize archive file pathing from "G305: Zip Slip vulnerability"
73+ func sanitizeArchivePath (d , t string ) (v string , err error ) {
74+ v = filepath .Join (d , t )
75+ if strings .HasPrefix (v , filepath .Clean (d )) {
76+ return v , nil
77+ }
78+
79+ return "" , fmt .Errorf ("%s: %s" , "content filepath is tainted" , t )
80+ }
81+
6982func tarGz (file , target string ) error {
7083 return tarinator .UnTarinate (target , file )
7184}
@@ -94,29 +107,45 @@ func tarXz(file, target string) error {
94107 if err != nil {
95108 return err
96109 }
97- switch hdr .Typeflag {
98- case tar .TypeDir :
99- // create a directory
100- // #nosec G305
101- err = os .MkdirAll (filepath .Join (target , hdr .Name ), 0o777 )
102- if err != nil {
103- return err
104- }
105- case tar .TypeReg :
106- // write a file
107- // #nosec G305
108- path := filepath .Join (target , hdr .Name )
109- w , err := os .Create (path )
110- if err != nil {
111- return err
112- }
113- // #nosec G110
114- _ , err = io .Copy (w , tr )
110+
111+ if err := tarXzFile (tr , hdr , target ); err != nil {
112+ return err
113+ }
114+
115+ }
116+ return nil
117+ }
118+
119+ func tarXzFile (tr * tar.Reader , hdr * tar.Header , target string ) error {
120+ path , err := sanitizeArchivePath (target , hdr .Name )
121+ if err != nil {
122+ return err
123+ }
124+ switch hdr .Typeflag {
125+ case tar .TypeDir :
126+ // create a directory
127+ err = os .MkdirAll (path , 0o777 )
128+ if err != nil {
129+ return err
130+ }
131+ case tar .TypeReg :
132+ // write a file
133+ w , err := os .Create (path )
134+ if err != nil {
135+ return err
136+ }
137+
138+ defer quietly .Close (w )
139+ for {
140+ _ , err := io .CopyN (w , tr , 1024 )
115141 if err != nil {
142+ if errors .Is (err , io .EOF ) {
143+ break
144+ }
116145 return err
117146 }
118- _ = w .Close ()
119147 }
148+
120149 }
121150 return nil
122151}
0 commit comments