Deny granular token requests admitted only by public access
What does this MR do and why?
!269281 (merged) serves a fine-grained PAT that only the public access rule of Authz::BoundaryPolicy admitted as anonymous in REST and GraphQL. The other callers of Authz::Tokens::AuthorizeGranularScopesService still treated that admission as a grant and read as the token's user.
This MR makes denial the default:
- The service returns an error for such a request, naming the token's missing permissions, unless the caller passes
allow_public_access: true. - REST and GraphQL opt in and keep serving these requests as anonymous.
- Git, LFS, repository archive and release link downloads opt in where anonymous users could make the same download, and the
get_pages_contentMCP tool for projects anonymous users can read. - Everything else denies: sessionless web requests (feeds, calendars, design images) return 404, the notes channel and
WikiPageChannelreject the subscription, the Orbit context and grep services treat the record as unreadable, and the other MCP custom tools deny the call.
Tokens that hold the permission, legacy tokens and granular OAuth tokens are not affected. On the denied paths an ungranted token now gets less than an anonymous request: Orbit and MCP tools need a signed-in user anyway, and a public feed, design image or notes subscription still works without the token. The existing raw image on a public project example now expects 404 instead of 200.
Specs cover each kind of denied caller with and without the permission, and check that REST, GraphQL, Git, LFS, archives, release downloads and Pages still serve an ungranted token on a public project.
References
- Follows !269281 (merged)
- Related to 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
- Pick a public project. As a user who is not a member of it, create a fine-grained personal access token whose only permission is on another project.
- Request the project's issues feed with the token:
With this MR the response is 404. Without the token, the public feed is returned.
curl --header "PRIVATE-TOKEN: <token>" "https://gdk.test:3000/<group>/<project>/-/issues.atom" - Clone the project over HTTP with the token. The clone still succeeds.
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.