mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-24 14:25:02 +02:00
fix(actions): drop untrusted Content-Encoding from v1 artifact uploads (#39855)
Legacy (v1 to v3) artifact uploads stored the request's `Content-Encoding` header in the column that v4 artifacts read as their `Content-Type`. - Store only the `gzip` marker on legacy uploads, the only encoding their clients send - Pick the PDF and audio/video serve headers only for content types that `mime.ParseMediaType` accepts --------- Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
1 parent
497e169398
commit
4f744d15be
4 files changed
+14
-8
No files matched your search
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
@@ -60,11 +61,13 @@ func serveSetHeaderContentRelated(w http.ResponseWriter, contentType string) {
|
||||
header.Set("X-Content-Type-Options", "nosniff")
|
||||
|
||||
csp := serveHeaderCspDefault
|
||||
if strings.HasPrefix(contentType, "application/pdf") {
|
||||
csp = serveHeaderCspPdf
|
||||
}
|
||||
if strings.HasPrefix(contentType, "video/") || strings.HasPrefix(contentType, "audio/") {
|
||||
csp = serveHeaderCspAudioVideo
|
||||
if mediaType, _, err := mime.ParseMediaType(contentType); err == nil { // browsers may parse malformed types differently
|
||||
if mediaType == "application/pdf" {
|
||||
csp = serveHeaderCspPdf
|
||||
}
|
||||
if strings.HasPrefix(mediaType, "video/") || strings.HasPrefix(mediaType, "audio/") {
|
||||
csp = serveHeaderCspAudioVideo
|
||||
}
|
||||
}
|
||||
if csp != "" {
|
||||
header.Set("Content-Security-Policy", csp)
|
||||
|
||||
@@ -117,9 +117,10 @@ func TestServeSetHeaderContentRelated(t *testing.T) {
|
||||
{"", serveHeaderCspDefault},
|
||||
{"any", serveHeaderCspDefault},
|
||||
{"application/pdf", serveHeaderCspPdf},
|
||||
{"application/pdf; other", serveHeaderCspPdf},
|
||||
{"application/pdf; charset=binary", serveHeaderCspPdf},
|
||||
{"audio/mp4", serveHeaderCspAudioVideo},
|
||||
{"video/ogg; other", serveHeaderCspAudioVideo},
|
||||
{"video/ogg; codecs=theora", serveHeaderCspAudioVideo},
|
||||
{"video/mp4;,text/html", serveHeaderCspDefault},
|
||||
{typesniffer.MimeTypeImageSvg, serveHeaderCspDefault},
|
||||
}
|
||||
for _, c := range cases {
|
||||
|
||||
@@ -281,7 +281,7 @@ func (ar artifactRoutes) uploadArtifact(ctx *ArtifactContext) {
|
||||
artifact.FileCompressedSize != chunksTotalSize {
|
||||
artifact.FileSize = fileRealTotalSize
|
||||
artifact.FileCompressedSize = chunksTotalSize
|
||||
artifact.ContentEncodingOrType = ctx.Req.Header.Get("Content-Encoding")
|
||||
artifact.ContentEncodingOrType = util.Iif(ctx.Req.Header.Get("Content-Encoding") == actions.ContentEncodingV3Gzip, actions.ContentEncodingV3Gzip, "") // other values could be served as a v4 Content-Type
|
||||
if err := actions.UpdateArtifact(ctx, artifact, "file_size", "file_compressed_size", "content_encoding"); err != nil {
|
||||
log.Error("Error update artifact: %v", err)
|
||||
ctx.HTTPError(http.StatusInternalServerError, "Error update artifact")
|
||||
|
||||
@@ -210,9 +210,11 @@ func TestActionsArtifactUploadSingleFile(t *testing.T) {
|
||||
req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body)).
|
||||
AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a").
|
||||
SetHeader("Content-Range", "bytes 0-1023/1024").
|
||||
SetHeader("Content-Encoding", "video/mp4,text/html").
|
||||
SetHeader("x-tfs-filelength", "1024").
|
||||
SetHeader("x-actions-results-md5", "XVlf820rMInUi64wmMi6EA==") // base64(md5(body))
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
assert.Empty(t, unittest.AssertExistsAndLoadBean(t, &actions_model.ActionArtifact{RunID: 791, ArtifactName: "artifact", ArtifactPath: "abc-2.txt"}).ContentEncodingOrType)
|
||||
|
||||
t.Logf("Create artifact confirm")
|
||||
|
||||
|
||||
Reference in new issue
Block a user