1616package main
1717
1818import (
19+ "bytes"
1920 "crypto/x509"
21+ "encoding/json"
2022 "encoding/pem"
23+ "io"
24+ "net/http"
25+ "net/http/httptest"
2126 "path/filepath"
2227 "testing"
2328
29+ "github.com/arduino/arduino-create-agent/upload"
30+ "github.com/gin-gonic/gin"
2431 "github.com/stretchr/testify/require"
2532)
2633
@@ -38,3 +45,39 @@ func TestValidSignatureKey(t *testing.T) {
3845 require .NoError (t , err )
3946 require .NotNil (t , key )
4047}
48+
49+ func TestUploadHandlerAgainstEvilFileNames (t * testing.T ) {
50+ r := gin .New ()
51+ r .POST ("/" , uploadHandler )
52+ ts := httptest .NewServer (r )
53+
54+ uploadEvilFileName := Upload {
55+ Port : "/dev/ttyACM0" ,
56+ Board : "arduino:avr:uno" ,
57+ Extra : upload.Extra {Network : true },
58+ Hex : []byte ("test" ),
59+ Filename : "../evil.txt" ,
60+ ExtraFiles : []additionalFile {{Hex : []byte ("test" ), Filename : "../evil.txt" }},
61+ }
62+ uploadEvilExtraFile := Upload {
63+ Port : "/dev/ttyACM0" ,
64+ Board : "arduino:avr:uno" ,
65+ Extra : upload.Extra {Network : true },
66+ Hex : []byte ("test" ),
67+ Filename : "file.txt" ,
68+ ExtraFiles : []additionalFile {{Hex : []byte ("test" ), Filename : "../evil.txt" }},
69+ }
70+
71+ for _ , request := range []Upload {uploadEvilFileName , uploadEvilExtraFile } {
72+ payload , err := json .Marshal (request )
73+ require .NoError (t , err )
74+
75+ resp , err := http .Post (ts .URL , "encoding/json" , bytes .NewBuffer (payload ))
76+ require .NoError (t , err )
77+ require .Equal (t , http .StatusBadRequest , resp .StatusCode )
78+
79+ body , err := io .ReadAll (resp .Body )
80+ require .NoError (t , err )
81+ require .Contains (t , string (body ), "unsafe path join" )
82+ }
83+ }
0 commit comments