66 "io"
77 "io/fs"
88 "os"
9+ "path"
910 "strings"
1011 "time"
1112)
@@ -128,6 +129,17 @@ func parseOctal(b []byte) uint64 {
128129 return sum
129130}
130131
132+ func sanitizeArchiveName (name string ) (string , error ) {
133+ cleaned := path .Clean (name )
134+ if cleaned == "." {
135+ return "" , fmt .Errorf ("cpio: invalid path %q" , name )
136+ }
137+ if cleaned == ".." || strings .HasPrefix (cleaned , "../" ) {
138+ return "" , fmt .Errorf ("cpio: path traversal %q" , name )
139+ }
140+ return cleaned , nil
141+ }
142+
131143func (r * Reader ) init (rdr io.ReaderAt , size int64 ) error {
132144 r .r = rdr
133145 r .size = size
@@ -171,6 +183,12 @@ func (r *Reader) init(rdr io.ReaderAt, size int64) error {
171183 }
172184 offset += int64 (nameSize )
173185 name := string (nameBuf [:nameSize - 1 ]) // Remove null terminator
186+ name = strings .TrimPrefix (name , "." )
187+ cleaned , err := sanitizeArchiveName (name )
188+ if err != nil {
189+ return err
190+ }
191+ name = cleaned
174192
175193 // Check for trailer
176194 // The MKS cpio page says "TRAILER!!"
@@ -191,7 +209,7 @@ func (r *Reader) init(rdr io.ReaderAt, size int64) error {
191209 }
192210
193211 // Add to files map using inode as key
194- r .Files [strings . TrimPrefix ( name , "." ) ] = & File {
212+ r .Files [name ] = & File {
195213 Info : FileInfo {
196214 DeviceNo : parseOctal (header .Dev [:]),
197215 Inode : parseOctal (header .Ino [:]),
@@ -202,7 +220,7 @@ func (r *Reader) init(rdr io.ReaderAt, size int64) error {
202220 RDev : int (parseOctal (header .RDev [:])),
203221 Mtime : time .Unix (int64 (int64 (parseOctal (header .MTime [:]))), 0 ),
204222 },
205- Name : strings . TrimPrefix ( name , "." ) ,
223+ Name : name ,
206224 Size : int64 (fileSize ),
207225 offset : offset ,
208226 length : int64 (fileSize ),
0 commit comments