@@ -19,11 +19,13 @@ import (
1919 "archive/zip"
2020 "bytes"
2121 "errors"
22+ "fmt"
2223 "io"
2324 "os"
2425 "os/exec"
2526 "path"
2627 "path/filepath"
28+ "strings"
2729)
2830
2931// SaveFileonTempDir creates a temp directory and saves the file data as the
@@ -32,15 +34,21 @@ import (
3234// Returns an error if the filename doesn't form a valid path.
3335//
3436// Note that path could be defined and still there could be an error.
35- func SaveFileonTempDir (filename string , data io.Reader ) (path string , err error ) {
36- // Create Temp Directory
37+ func SaveFileonTempDir (filename string , data io.Reader ) (string , error ) {
3738 tmpdir , err := os .MkdirTemp ("" , "arduino-create-agent" )
3839 if err != nil {
3940 return "" , errors .New ("Could not create temp directory to store downloaded file. Do you have permissions?" )
4041 }
42+ return saveFileonTempDir (tmpdir , filename , data )
43+ }
4144
45+ func saveFileonTempDir (tmpDir , filename string , data io.Reader ) (string , error ) {
46+ path , err := SafeJoin (tmpDir , filename )
47+ if err != nil {
48+ return "" , err
49+ }
4250 // Determine filename
43- filename , err = filepath .Abs (tmpdir + "/" + filename )
51+ filename , err = filepath .Abs (path )
4452 if err != nil {
4553 return "" , err
4654 }
@@ -141,3 +149,16 @@ func Unzip(zippath string, destination string) (err error) {
141149 }
142150 return
143151}
152+
153+ // SafeJoin performs a filepath.Join of 'parent' and 'subdir' but returns an error
154+ // if the resulting path points outside of 'parent'.
155+ func SafeJoin (parent , subdir string ) (string , error ) {
156+ res := filepath .Join (parent , subdir )
157+ if ! strings .HasSuffix (parent , string (os .PathSeparator )) {
158+ parent += string (os .PathSeparator )
159+ }
160+ if ! strings .HasPrefix (res , parent ) {
161+ return res , fmt .Errorf ("unsafe path join: '%s' with '%s'" , parent , subdir )
162+ }
163+ return res , nil
164+ }
0 commit comments