Skip to content

Filter private users from reviewer list#37414

Draft
pisarz77 wants to merge 2 commits intogo-gitea:mainfrom
pisarz77:fix/reviewer-visibility-37371
Draft

Filter private users from reviewer list#37414
pisarz77 wants to merge 2 commits intogo-gitea:mainfrom
pisarz77:fix/reviewer-visibility-37371

Conversation

@pisarz77
Copy link
Copy Markdown
Contributor

@pisarz77 pisarz77 commented Apr 25, 2026

Summary

Fix #37371: services/pull.GetReviewers returned every active candidate without checking user.visibility. Non-admin callers of GET /api/v1/repos/{owner}/{repo}/reviewers and the web reviewer picker therefore saw users with visibility=private that should be hidden.

What changed

  • services/pull/reviewer.go — apply user_model.BuildCanSeeUserCondition(doer) for admin/visibility handling.
  • Function signature: GetReviewers(ctx, repo, doer *user_model.User, posterID int64) — both callers already had ctx.Doer, so no extra DB lookup is required.
  • Updated callers in routers/api/v1/repo/collaborators.go and routers/web/repo/issue_page_meta.go.
  • Added TestRepoGetReviewersAppliesVisibility regression test using existing fixtures (repo4 owned by user5, restricted user29 as collaborator). Restricted collaborators remain selectable; only visibility hides users.

Why this PR

The visibility filter was missing in the original query, but the helper-based path introduced in #37365 widened the candidate set (team.authorize >= ? OR team_unit.access_mode >= ?), making the leak more reproducible — private team members previously hidden by the strict per-unit access check are now reached. Filtering at the final user query closes the gap without reverting #37365.

is_restricted is intentionally not used as a filter: a restricted user only enters the candidate set when they have explicit collaborator or team access to the repo, in which case they are a legitimate reviewer.

Test plan

  • go test -run TestRepoGetReviewers -count=1 -tags="sqlite sqlite_unlock_notify" ./services/pull/... — pass
  • go vet ./services/pull/... ./routers/api/v1/repo/... ./routers/web/repo/... — clean
  • Manual fixture trace: non-admin doer (user5) on repo4 still sees public restricted collaborator user29; private-visibility users no longer leak.

Fixes #37371

`services/pull.GetReviewers` returned every active candidate without
checking `user.visibility` or `user.is_restricted`. Non-admin callers of
`GET /api/v1/repos/{owner}/{repo}/reviewers` and the web reviewer picker
therefore saw users with `visibility=private` and `is_restricted=true`
that would otherwise be hidden from them.

The pre-existing direct-join already lacked the visibility check, but
the helper-based query introduced in go-gitea#37365 widened the candidate set
(team-level `authorize` OR per-unit `access_mode`), making the leak
more reproducible. This change applies the standard
`user_model.BuildCanSeeUserCondition` for admin/visibility handling and
additionally excludes `is_restricted=true` users for non-admin doers,
which the helper does not cover.

`GetReviewers` now takes the doer `*user_model.User` directly instead
of `doerID int64`; both callers (`routers/api/v1/repo/collaborators.go`
and `routers/web/repo/issue_page_meta.go`) already had `ctx.Doer`
available, so no extra DB lookup is needed.

Adds `TestRepoGetReviewersHidesPrivateAndRestricted` as a regression
guard using existing fixtures (repo4 owned by user5, with restricted
user29 as collaborator).

Fix go-gitea#37371

Signed-off-by: Jakub Pisarczyk <pisarz77@gmail.com>
@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Apr 25, 2026
Comment thread services/pull/reviewer.go Outdated
cond = cond.And(visCond)
}
if doer == nil || !doer.IsAdmin {
cond = cond.And(builder.Eq{"`user`.is_restricted": false})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — that filter is too aggressive. is_restricted=true only restricts what a user can see, not whether they can be requested as a reviewer. Restricted users only enter uniqueUserIDs when they have explicit collaborator/team access to the repo, so excluding them blocks legitimate reviewers (e.g. an outside collaborator who is restricted at the instance level).

The actual leak in #37371 is visibility=private users showing up — that's covered by BuildCanSeeUserCondition. I've dropped the is_restricted=false clause and updated the regression test (TestRepoGetReviewersAppliesVisibility) to assert that a restricted collaborator stays selectable. Pushed as 88f7dd7. PR title/description updated accordingly.

@wxiaoguang wxiaoguang marked this pull request as draft April 25, 2026 07:51
Filtering out is_restricted=true users was too aggressive: restricted
users only enter the candidate set when they have explicit collaborator
or team access to the repo, so excluding them blocks legitimate
reviewers. The actual leak in go-gitea#37371 is visibility=private users, which
is already covered by BuildCanSeeUserCondition.

Update TestRepoGetReviewersHidesPrivateAndRestricted accordingly:
rename to TestRepoGetReviewersAppliesVisibility and assert that a
restricted collaborator (user29) stays selectable for both admin and
non-admin doers.
@pisarz77 pisarz77 changed the title Filter private and restricted users from reviewer list Filter private users from reviewer list Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Private users can be selected as a reviewer

3 participants