diff --git a/routers/web/repo/actions/badge.go b/routers/web/repo/actions/badge.go index dd733dca6e7..01a78a7f190 100644 --- a/routers/web/repo/actions/badge.go +++ b/routers/web/repo/actions/badge.go @@ -10,6 +10,7 @@ import ( "strings" actions_model "gitea.dev/models/actions" + auth_model "gitea.dev/models/auth" "gitea.dev/modules/badge" "gitea.dev/modules/git" "gitea.dev/modules/util" @@ -17,6 +18,11 @@ import ( ) func GetWorkflowBadge(ctx *context.Context) { + context.CheckRepoScopedToken(ctx, ctx.Repo.Repository, auth_model.Read) + if ctx.Written() { + return + } + workflowFile := ctx.PathParam("workflow_name") branch := ctx.FormString("branch", ctx.Repo.Repository.DefaultBranch) event := ctx.FormString("event") diff --git a/tests/integration/repo_home_token_scope_test.go b/tests/integration/repo_home_token_scope_test.go index 7010a44cf8c..7404fde401a 100644 --- a/tests/integration/repo_home_token_scope_test.go +++ b/tests/integration/repo_home_token_scope_test.go @@ -11,30 +11,33 @@ import ( "gitea.dev/tests" ) -// TestRepoHomeContentTokenScopes ensures the web repository home page enforces the -// repository read scope (and public-only confinement) of an API token used via basic -// auth, so a wrongly-scoped token cannot read private repository content. -func TestRepoHomeContentTokenScopes(t *testing.T) { +func TestRepoWebTokenScopes(t *testing.T) { defer tests.PrepareTestEnv(t)() - // user2/repo2 is a private repository owned by user2 - const url = "/user2/repo2" - - // a token without repository scope must be denied miscToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadMisc) - reqDenied := NewRequest(t, "GET", url) - reqDenied.SetBasicAuth("user2", miscToken) - MakeRequest(t, reqDenied, http.StatusForbidden) - - // a public-only token must be denied on a private repo publicOnlyToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository, auth_model.AccessTokenScopePublicOnly) - reqPublicOnly := NewRequest(t, "GET", url) - reqPublicOnly.SetBasicAuth("user2", publicOnlyToken) - MakeRequest(t, reqPublicOnly, http.StatusForbidden) + readToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository) - // a token with repository read scope is allowed - ownerReadToken := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository) - reqAllowed := NewRequest(t, "GET", url) - reqAllowed.SetBasicAuth("user2", ownerReadToken) - MakeRequest(t, reqAllowed, http.StatusOK) + for _, test := range []struct { + name string + url string + }{ + {"repository home", "/user2/repo2"}, + {"workflow badge", "/org3/repo3/actions/workflows/test.yml/badge.svg"}, + } { + t.Run(test.name, func(t *testing.T) { + assertBasicAuthStatus(t, test.url, miscToken, http.StatusForbidden) + assertBasicAuthStatus(t, test.url, publicOnlyToken, http.StatusForbidden) + assertBasicAuthStatus(t, test.url, readToken, http.StatusOK) + }) + } + + assertBasicAuthStatus(t, "/user2/repo1/actions/workflows/test.yml/badge.svg", publicOnlyToken, http.StatusOK) +} + +func assertBasicAuthStatus(t *testing.T, url, token string, status int) { + t.Helper() + req := NewRequest(t, http.MethodGet, url) + req.SetBasicAuth("user2", token) + MakeRequest(t, req, status) }