fix(web): enforce token scopes on raw, media, and attachment downloads (#37698) (#37733)

This commit is contained in:
Giteabot
2026-05-16 09:18:44 -07:00
committed by GitHub
parent ab0d52b4c7
commit 2965b0c08a
5 changed files with 286 additions and 36 deletions
+98
View File
@@ -7,6 +7,7 @@ import (
"net/http"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
@@ -14,6 +15,13 @@ import (
"github.com/stretchr/testify/assert"
)
type downloadScopeCase struct {
name string
url string
withScope int
publicOnlyOK bool
}
func TestDownloadRepoContent(t *testing.T) {
defer tests.PrepareTestEnv(t)()
@@ -71,3 +79,93 @@ func TestDownloadRepoContent(t *testing.T) {
assert.Equal(t, "application/xml", resp.Header().Get("Content-Type"))
})
}
func TestDownloadRepoContentTokenScopes(t *testing.T) {
defer tests.PrepareTestEnv(t)()
ownerReadToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository)
miscToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadMisc)
publicOnlyToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository, auth_model.AccessTokenScopePublicOnly)
cases := []downloadScopeCase{
{
name: "PublicRawBlob",
url: "/user2/repo1/raw/blob/4b4851ad51df6a7d9f25c979345979eaeb5b349f",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicRawBranch",
url: "/user2/repo1/raw/branch/master/README.md",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicRawTag",
url: "/user2/repo1/raw/tag/v1.1/README.md",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicRawCommit",
url: "/user2/repo1/raw/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d/README.md",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicMediaBlob",
url: "/user2/repo1/media/blob/4b4851ad51df6a7d9f25c979345979eaeb5b349f",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicMediaBranch",
url: "/user2/repo1/media/branch/master/README.md",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicMediaTag",
url: "/user2/repo1/media/tag/v1.1/README.md",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PublicMediaCommit",
url: "/user2/repo1/media/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d/README.md",
withScope: http.StatusOK,
publicOnlyOK: true,
},
{
name: "PrivateRawBranch",
url: "/user2/repo2/raw/branch/master/test.xml",
withScope: http.StatusOK,
publicOnlyOK: false,
},
{
name: "PrivateRawBlob",
url: "/user2/repo2/raw/blob/6395b68e1feebb1e4c657b4f9f6ba2676a283c0b",
withScope: http.StatusOK,
publicOnlyOK: false,
},
{
name: "PrivateMediaBranch",
url: "/user2/repo2/media/branch/master/test.xml",
withScope: http.StatusOK,
publicOnlyOK: false,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
MakeRequest(t, NewRequest(t, "GET", tc.url).AddTokenAuth(miscToken), http.StatusForbidden)
MakeRequest(t, NewRequest(t, "GET", tc.url).AddTokenAuth(ownerReadToken), tc.withScope)
publicOnlyStatus := http.StatusForbidden
if tc.publicOnlyOK {
publicOnlyStatus = tc.withScope
}
MakeRequest(t, NewRequest(t, "GET", tc.url).AddTokenAuth(publicOnlyToken), publicOnlyStatus)
})
}
}