@@ -7,12 +7,14 @@ import (
77 "bytes"
88 "crypto/sha256"
99 "encoding/hex"
10+ "encoding/xml"
1011 "io"
1112 "net/http"
1213 "strings"
1314 "testing"
1415 "time"
1516
17+ "code.gitea.io/gitea/modules/storage"
1618 "code.gitea.io/gitea/routers/api/actions"
1719 actions_service "code.gitea.io/gitea/services/actions"
1820 "code.gitea.io/gitea/tests"
@@ -170,6 +172,69 @@ func TestActionsArtifactV4UploadSingleFileWithRetentionDays(t *testing.T) {
170172 assert .True (t , finalizeResp .Ok )
171173}
172174
175+ func TestActionsArtifactV4UploadSingleFileWithPotentialHarmfulBlockID (t * testing.T ) {
176+ defer tests .PrepareTestEnv (t )()
177+
178+ token , err := actions_service .CreateAuthorizationToken (48 , 792 , 193 )
179+ assert .NoError (t , err )
180+
181+ // acquire artifact upload url
182+ req := NewRequestWithBody (t , "POST" , "/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact" , toProtoJSON (& actions.CreateArtifactRequest {
183+ Version : 4 ,
184+ Name : "artifactWithPotentialHarmfulBlockID" ,
185+ WorkflowRunBackendId : "792" ,
186+ WorkflowJobRunBackendId : "193" ,
187+ })).AddTokenAuth (token )
188+ resp := MakeRequest (t , req , http .StatusOK )
189+ var uploadResp actions.CreateArtifactResponse
190+ protojson .Unmarshal (resp .Body .Bytes (), & uploadResp )
191+ assert .True (t , uploadResp .Ok )
192+ assert .Contains (t , uploadResp .SignedUploadUrl , "/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact" )
193+
194+ // get upload urls
195+ idx := strings .Index (uploadResp .SignedUploadUrl , "/twirp/" )
196+ url := uploadResp .SignedUploadUrl [idx :] + "&comp=block&blockid=%2f..%2fmyfile"
197+ blockListUrl := uploadResp .SignedUploadUrl [idx :] + "&comp=blocklist"
198+
199+ // upload artifact chunk
200+ body := strings .Repeat ("A" , 1024 )
201+ req = NewRequestWithBody (t , "PUT" , url , strings .NewReader (body ))
202+ MakeRequest (t , req , http .StatusCreated )
203+
204+ // verify that the exploit didn't work
205+ _ , err = storage .Actions .Stat ("myfile" )
206+ assert .Error (t , err )
207+
208+ // upload artifact blockList
209+ blockList := & actions.BlockList {
210+ Latest : []string {
211+ "/../myfile" ,
212+ },
213+ }
214+ rawBlockList , err := xml .Marshal (blockList )
215+ assert .NoError (t , err )
216+ req = NewRequestWithBody (t , "PUT" , blockListUrl , bytes .NewReader (rawBlockList ))
217+ MakeRequest (t , req , http .StatusCreated )
218+
219+ t .Logf ("Create artifact confirm" )
220+
221+ sha := sha256 .Sum256 ([]byte (body ))
222+
223+ // confirm artifact upload
224+ req = NewRequestWithBody (t , "POST" , "/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact" , toProtoJSON (& actions.FinalizeArtifactRequest {
225+ Name : "artifactWithPotentialHarmfulBlockID" ,
226+ Size : 1024 ,
227+ Hash : wrapperspb .String ("sha256:" + hex .EncodeToString (sha [:])),
228+ WorkflowRunBackendId : "792" ,
229+ WorkflowJobRunBackendId : "193" ,
230+ })).
231+ AddTokenAuth (token )
232+ resp = MakeRequest (t , req , http .StatusOK )
233+ var finalizeResp actions.FinalizeArtifactResponse
234+ protojson .Unmarshal (resp .Body .Bytes (), & finalizeResp )
235+ assert .True (t , finalizeResp .Ok )
236+ }
237+
173238func TestActionsArtifactV4DownloadSingle (t * testing.T ) {
174239 defer tests .PrepareTestEnv (t )()
175240
0 commit comments