Serve bypass-admitted granular token requests as anonymous
What does this MR do and why?
A fine-grained PAT without a matching scope reaches a public project or group through the public access rule in Authz::BoundaryPolicy. The endpoint then authorized and filtered for the token's user, so a member's token got the member view: confidential issues, pipelines hidden when Public pipelines is off, pipeline schedule variables, and the same data in GraphQL.
This MR serves those requests as anonymous:
AuthorizeGranularScopesServicereports when only the public access rule admitted the token.- REST:
current_userreturnsnilfor those requests, andunauthorized!denies them withinsufficient_granular_scopeinstead of401 Unauthorized. Logs and audit events still record the token's user. - GraphQL:
context[:current_user]isnilfor the object the rule admitted and everything resolved below it. A child whose own permission the token holds gets the user back. A mutation admitted only by the rule is denied. - GraphQL: the merge request count batch is keyed on the current user. Without the key, one query that read an issue the token holds
read_issuefor and an issue on a public project counted both with the member's view. No other batch loader mixes users this way. - The granular token shared example now checks that a scopeless token gets the same response as an anonymous request on public boundaries, for a non-member and for the spec's
user.
On public projects, a non-member's scopeless token now gets 403 on endpoints that require authentication, such as pipeline schedules, where it used to get 200.
In GraphQL, a field on an object admitted by the public access rule resolves as anonymous even when the token holds the permission of the field's type. That denies more than needed but leaks nothing.
PSIRT approved fixing this in public, so this replaces the earlier MR on the security fork.
References
- Fixes https://gitlab.com/gitlab-org/gitlab/-/work_items/625976
- Fixes https://gitlab.com/gitlab-org/gitlab/-/work_items/637548
Screenshots or screen recordings
Not applicable, no UI change.
How to set up and validate locally
- Make sure the
granular_personal_access_tokensfeature flag is enabled. - As a member of a public project that has a confidential issue, create a fine-grained personal access token with no permissions.
- List the confidential issues with the token:
On
curl --header "PRIVATE-TOKEN: <token>" "https://gdk.test:3000/api/v4/projects/<project_id>/issues?confidential=true"masterthe confidential issue is returned. With this MR the response is empty, the same as a request without a token.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.