Skip to content

Commit d9f55bc

Browse files
committed
add test to verify exploit failure
1 parent 5a2a395 commit d9f55bc

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

tests/integration/api_actions_artifact_v4_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
173238
func TestActionsArtifactV4DownloadSingle(t *testing.T) {
174239
defer tests.PrepareTestEnv(t)()
175240

0 commit comments

Comments
 (0)