jojo/services
Mathieu Fenniak 99984dac4d feat: remove admin-level permissions from repo-specific & public-only access tokens (#11468)
This PR is part of a series (#11311).

If the user authenticating to an API call is a Forgejo site administrator, or a Forgejo repo administrator, a wide variety of permission and ownership checks in the API are either bypassed, or are bypassable.  If a user has created an access token with restricted resources, I understand the intent of the user is to create a token which has a layer of risk reduction in the event that the token is lost/leaked to an attacker.  For this reason, it makes sense to me that restricted scope access tokens shouldn't inherit the owner's administrator access.

My intent is that repo-specific access tokens [will only be able to access specific authorization scopes](https://codeberg.org/forgejo/design/issues/50#issuecomment-11093951), probably: `repository:read`, `repository:write`, `issue:read`, `issue:write`, (`organization:read` / `user:read` maybe).  This means that *most* admin access is not intended to be affected by this because repo-specific access tokens won't have, for example, `admin:write` scope.  However, administrative access still grants elevated permissions in some areas that are relevant to these scopes, and need to be restricted:

- The `?sudo=otheruser` query parameter allows site administrators to impersonate other users in the API.
- Repository management rules are different for a site administrator, allowing them to create repos for another user, create repos in another organization, migrate a repository to an arbitrary owner, and transfer a repository to a prviate organization.
- Administrators have access to extra data through some APIs which would be in scope: the detailed configuration of branch protection rules, the some details of repository deploy keys (which repo, and which scope -- seems odd), (user:read -- user SSH keys, activity feeds of private users, user profiles of private users, user webhook configurations).
- Pull request reviews have additional perms for repo administrators, including the ability to dismiss PR reviews, delete PR reviews, and view draft PR reviews.
- Repo admins and site admins can comment on locked issues, and related to comments can edit or delete other user's comments and attachments.
- Repo admins can manage and view logged time on behalf of other users.

A handful of these permissions may make sense for repo-specific access tokens, but most of them clearly exceed the risk that would be expected from creating a limited scope access token.  I'd generally prefer to take a restrictive approach, and we can relax it if real-world use-cases come in -- users will have a workaround of creating an access token without repo-specific restrictions if they are blocked from needed access.

**Breaking:** The administration restrictions introduced in this PR affect both repo-specific access tokens, and existing public-only access tokens.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
    - Although repo-specific access tokens are not yet exposed to end users, the breaking changes to public-only tokens will be visible to users and require release notes.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11468
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-03-04 16:17:41 +01:00
..
actions Revert "fix: ensure actions logs are transferred when a task is done (#10008)" (#11462) 2026-03-02 15:34:09 +01:00
agit chore: fix typos throughout the codebase (#10753) 2026-01-26 22:57:33 +01:00
asymkey chore: do not clobber ~/.ssh/authorized_keys in certain tests (#10163) 2025-11-19 16:14:16 +01:00
attachment chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00
auth feat: add APIContext.Reducer computed from access token 2026-02-27 17:17:29 +01:00
authz refactor: split AuthorizationReducer into a base RepositoryAuthorizationReducer interface 2026-03-01 17:05:53 +01:00
automerge fix: check PR reference on base repository (#8431) 2025-07-06 14:23:47 +02:00
context feat: remove admin-level permissions from repo-specific & public-only access tokens (#11468) 2026-03-04 16:17:41 +01:00
contexttest Replace the 'relative-time' element scripting with custom, translatable rewrite (#6154) 2025-05-03 14:11:01 +00:00
convert feat: implement ephemeral runners (#9962) 2026-02-16 18:56:56 +01:00
cron fix: garbage collect lingering actions logs (#10009) 2025-11-18 18:59:01 +01:00
doctor chore: fix typos throughout the codebase (#10753) 2026-01-26 22:57:33 +01:00
externalaccount chore(cleanup): replaces unnecessary calls to formatting functions by non-formatting equivalents (#7994) 2025-05-29 17:34:29 +02:00
f3 chore: update gof3/v3 v3.11.15 (#10673) 2026-01-13 16:59:56 +01:00
federation feat(activitypub): use structure @PreferredUsername@host.tld:port for actors (#9254) 2026-01-30 23:45:11 +01:00
feed chore: fix typos throughout the codebase (#10753) 2026-01-26 22:57:33 +01:00
forgejo chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00
forms feat: allow sync quota groups with oauth2 auth source (#8554) 2025-12-01 14:12:00 +01:00
gitdiff refactor: replace Value() from Option[T] with Get() & ValueOrZeroValue() (#11218) 2026-02-10 16:41:21 +01:00
indexer chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
issue feat: implement fine-grained access tokens in /repos/{owner}/{repo}/pulls/{index}/requested_reviewers 2026-03-01 17:05:53 +01:00
lfs fix: return on error if an LFS token cannot be parsed 2025-10-25 10:41:49 -06:00
mailer fix: don't display pending reviews as participants (#10528) 2026-01-06 10:47:21 +01:00
markup chore: remove branding from context imports (#9628) 2025-10-11 01:52:51 +02:00
migrations fix: prevent panic on gitlab import (releases/issues) (#11282) 2026-03-03 21:36:14 +01:00
mirror fix: don't push LFS when using SSH authentication (#10475) 2025-12-18 23:23:07 +01:00
moderation chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00
notify chore: Dead Code: DeleteIssue Notify Topic (#10046) 2025-11-17 02:13:38 +01:00
org chore: fix typos throughout the codebase (#10753) 2026-01-26 22:57:33 +01:00
packages fix: cleanup of multi-platform container images (#11246) 2026-02-12 03:12:32 +01:00
pull fix: correct Reviewed-on URL in merge message for subpath deployments (#11240) 2026-02-11 18:12:29 +01:00
redirect chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00
release chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00
remote chore: fix typos throughout the codebase (#10753) 2026-01-26 22:57:33 +01:00
repository feat: implement ephemeral runners (#9962) 2026-02-16 18:56:56 +01:00
secrets fix: normalize secrets consistently, display accurate help (#11052) 2026-02-09 17:02:18 +01:00
shared/automerge fix: suppress false-positive error log when PR is already in the automerge queue (#9784) 2025-10-21 08:19:33 +02:00
stats chore: fix typos throughout the codebase (#10753) 2026-01-26 22:57:33 +01:00
task feat: cache derived keys for faster keying (#10114) 2025-11-16 14:29:14 +01:00
uinotification chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
user refactor: replace Value() from Option[T] with Get() & ValueOrZeroValue() (#11218) 2026-02-10 16:41:21 +01:00
webhook fix: allow test delivery for webhooks not enabled for push events (#11073) 2026-01-27 23:19:34 +01:00
wiki chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00