fix(api): deny private org member enumeration via /members (#38213)

This commit is contained in:
bircni
2026-06-26 20:35:13 +02:00
committed by GitHub
parent 1b0992eb2e
commit 122ebcf0a8
3 changed files with 8 additions and 13 deletions

View File

@@ -1719,7 +1719,7 @@ func Routes() *web.Router {
m.Get("", reqToken(), org.ListMembers)
m.Combo("/{username}").Get(reqToken(), org.IsMember).
Delete(reqToken(), reqOrgOwnership(), org.DeleteMember)
})
}, reqOrgVisible())
addActionsRoutes(
m,
reqOrgMembership(),
@@ -1731,7 +1731,7 @@ func Routes() *web.Router {
m.Combo("/{username}").Get(org.IsPublicMember).
Put(reqToken(), reqOrgMembership(), org.PublicizeMember).
Delete(reqToken(), reqOrgMembership(), org.ConcealMember)
})
}, reqOrgVisible())
m.Group("/teams", func() {
m.Get("", org.ListTeams)
m.Post("", reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)

View File

@@ -119,12 +119,6 @@ func ListPublicMembers(ctx *context.APIContext) {
// "404":
// "$ref": "#/responses/notFound"
// don't disclose membership of organizations the doer cannot see
if !organization.HasOrgOrUserVisible(ctx, ctx.Org.Organization.AsUser(), ctx.Doer) {
ctx.APIErrorNotFound()
return
}
listMembers(ctx, false)
}
@@ -207,11 +201,6 @@ func IsPublicMember(ctx *context.APIContext) {
if ctx.Written() {
return
}
// don't disclose membership of organizations the doer cannot see
if !organization.HasOrgOrUserVisible(ctx, ctx.Org.Organization.AsUser(), ctx.Doer) {
ctx.APIErrorNotFound()
return
}
is, err := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, userToCheck.ID)
if err != nil {
ctx.APIErrorInternal(err)

View File

@@ -284,10 +284,16 @@ func TestAPIOrgPrivateMembersNotLeaked(t *testing.T) {
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", "/api/v1/orgs/"+orgName+"/public_members").AddTokenAuth(outsiderToken)
MakeRequest(t, req, http.StatusNotFound)
// the full member list of a private org must not be enumerable by an outsider either
req = NewRequest(t, "GET", "/api/v1/orgs/"+orgName+"/members").AddTokenAuth(outsiderToken)
MakeRequest(t, req, http.StatusNotFound)
// the member can still see the public membership of their own org
req = NewRequest(t, "GET", "/api/v1/orgs/"+orgName+"/public_members/"+memberName).AddTokenAuth(memberToken)
MakeRequest(t, req, http.StatusNoContent)
// and the member can still list the org's members
req = NewRequest(t, "GET", "/api/v1/orgs/"+orgName+"/members").AddTokenAuth(memberToken)
MakeRequest(t, req, http.StatusOK)
}
func testAPIDeleteOrgRepos(t *testing.T) {