ci: add semgrep detection for API code ignoring repo-specific access tokens #11476

Merged
mfenniak merged 5 commits from finegrained-pr7-semgrep into forgejo 2026-03-03 17:55:37 +01:00
Member

This PR is part of a series (#11311).

Prevents the usage of three internal APIs in the web API code:

  • repo_model.SearchRepoOptions{} without an AuthorizationReducer
  • organization.SearchTeamRepoOptions{} without an AuthorizationReducer
  • access_model.GetUserRepoPermission(), which doesn't take an AuthorizationReducer -- use GetUserRepoPermissionWithReducer instead.

A couple lingering usages are marked with // nosemgrep: ... as they have been inspected and considered correct as-is.

The GetUserRepoPermission is tested via the .semgrep/tests files; the other rules have been tested manually.

Checklist

The contributor guide contains information that will be helpful to first time contributors. There also are a few conditions for merging Pull Requests in Forgejo repositories. You are also welcome to join the Forgejo development chatroom.

Documentation

  • I created a pull request to the documentation to explain to Forgejo users how to use this change.
  • I did not document these changes and I do not expect someone else to do it.

Release notes

  • 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.
  • 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.
This PR is part of a series (#11311). Prevents the usage of three internal APIs in the web API code: - `repo_model.SearchRepoOptions{}` without an `AuthorizationReducer` - `organization.SearchTeamRepoOptions{}` without an `AuthorizationReducer` - `access_model.GetUserRepoPermission()`, which doesn't take an `AuthorizationReducer` -- use `GetUserRepoPermissionWithReducer` instead. A couple lingering usages are marked with `// nosemgrep: ...` as they have been inspected and considered correct as-is. The `GetUserRepoPermission` is tested via the `.semgrep/tests` files; the other rules have been tested manually. ## 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). ### 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 - [ ] 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. - [x] 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.
ci: add semgrep detection for incorrect GetUserRepoPermission
All checks were successful
issue-labels / backporting (pull_request_target) Has been skipped
testing / semgrep/ci (pull_request) Successful in 18s
issue-labels / cascade (pull_request_target) Has been skipped
Integration tests for the release process / release-simulation (push) Successful in 5m34s
issue-labels / release-notes (pull_request_target) Has been skipped
requirements / merge-conditions (pull_request) Successful in 3s
testing / frontend-checks (pull_request) Successful in 1m21s
testing / backend-checks (pull_request) Successful in 3m37s
testing / test-unit (pull_request) Successful in 7m50s
testing / test-remote-cacher (redis) (pull_request) Successful in 2m24s
testing / test-remote-cacher (valkey) (pull_request) Successful in 3m12s
testing / test-remote-cacher (redict) (pull_request) Successful in 2m25s
testing / test-remote-cacher (garnet) (pull_request) Successful in 2m28s
testing / test-mysql (pull_request) Successful in 28m18s
testing / test-e2e (pull_request) Successful in 28m20s
testing / test-sqlite (pull_request) Successful in 34m23s
testing / test-pgsql (pull_request) Successful in 40m39s
testing / security-check (pull_request) Successful in 1m44s
a274a3d662
Whenever GetUserRepoPermission is invoked with a `*context.APIContext`,
or whenever it is invoked from code in `routers/api`, a semgrep-powered
error will identify that fine-grained access token limitations aren't
implemented and that GetUserRepoPermissionWithReducer may be preferred.
@ -171,0 +173,4 @@
// permission checks. Repo-specific access tokens aren't expected to be used with `package:write` scope, so
// there's currently no need to change this to GetUserRepoPermissionWithReducer -- and because package APIs
// doesn't take use an `APIContext`, we don't have access to a reducer to provide to it.
//
Member

Repo-specific access tokens aren't expected to be used with package:write scope.

I don't follow. Packages, at least OCI images, can be attached to repositories.

In any case, I find the description a bit unclear. I tried to reword it:

AuthorizationReducer is not applicable to this usage of GetUserRepoPermission() because it is used to figure out whether the user has the permission package:write. Repository-specific access tokens are not supposed to curtail package:write.
> Repo-specific access tokens aren't expected to be used with `package:write` scope. I don't follow. Packages, at least OCI images, can be attached to repositories. In any case, I find the description a bit unclear. I tried to reword it: ``` AuthorizationReducer is not applicable to this usage of GetUserRepoPermission() because it is used to figure out whether the user has the permission package:write. Repository-specific access tokens are not supposed to curtail package:write. ```
Author
Member

@aahlenst wrote in #11476 (comment):

Repo-specific access tokens aren't expected to be used with package:write scope.

I don't follow. Packages, at least OCI images, can be attached to repositories.

Repo-specific access tokens will be restricted to only providing the read:repository, write:repository, read:issue, and write:issue scopes. Any other configuration will fail to create an access token (I'm still authoring the PRs to create repo-specific access tokens, so I don't have code to link here). This is the meaning of the statement "Repo-specific access tokens aren't expected to be used with package:write scope."

I'll take a pass at rewriting this comment to clarify it.

@aahlenst wrote in https://codeberg.org/forgejo/forgejo/pulls/11476#issuecomment-11163926: > > Repo-specific access tokens aren't expected to be used with `package:write` scope. > > I don't follow. Packages, at least OCI images, can be attached to repositories. Repo-specific access tokens will be restricted to only providing the `read:repository`, `write:repository`, `read:issue`, and `write:issue` scopes. Any other configuration will fail to create an access token (I'm still authoring the PRs to create repo-specific access tokens, so I don't have code to link here). This is the meaning of the statement "Repo-specific access tokens aren't expected to be used with `package:write` scope." I'll take a pass at rewriting this comment to clarify it.
Author
Member

Revision a274a3d662..a8fef29b10:

// GetUserRepoPermission is used, which doesn't take into account any `AuthorizationReducer` from access
// tokens.  At present, `AuthorizationReducer` only provides capabilities to implement repo-specific access
// tokens.  It is not possible to create a repo-specific access token with the `package:write` scope, and
// that scope is required to call this API, so implementing `AuthorizationReducer` is not necessary here.
//
// This access check would need revision if either: package-specific access tokens were created, or,
// `package:write` scope was permitted on a repo-specific access token.
//
// (Because package APIs doesn't take use an `APIContext`, we don't have access to a reducer to provide to
// GetUserRepoPermissionWithReducer, otherwise we'd just do it and not spend so much time describing why we
// don't have to.)
//
// nosemgrep: forgejo-api-suspicious-GetUserRepoPermission

(The fact that this is a weird access check is removed from the comment because it's irrelevant to the ignore. While packages in general can be linked to repositories, as you've noted, this appears to be the only access check in the package API that looks for permission to write to the linked repository. 🤷 It stands out as a possible mistake, but, not really relevant to why we can ignore repo-specific access tokens here.)

Revision https://codeberg.org/forgejo/forgejo/compare/a274a3d66253075ce278bc187bf14f71904609a7..a8fef29b1024d70ea5b0619b345ce9177c76057b: ```go // GetUserRepoPermission is used, which doesn't take into account any `AuthorizationReducer` from access // tokens. At present, `AuthorizationReducer` only provides capabilities to implement repo-specific access // tokens. It is not possible to create a repo-specific access token with the `package:write` scope, and // that scope is required to call this API, so implementing `AuthorizationReducer` is not necessary here. // // This access check would need revision if either: package-specific access tokens were created, or, // `package:write` scope was permitted on a repo-specific access token. // // (Because package APIs doesn't take use an `APIContext`, we don't have access to a reducer to provide to // GetUserRepoPermissionWithReducer, otherwise we'd just do it and not spend so much time describing why we // don't have to.) // // nosemgrep: forgejo-api-suspicious-GetUserRepoPermission ``` (The fact that this is a weird access check is removed from the comment because it's irrelevant to the ignore. While packages in general can be linked to repositories, as you've noted, this appears to be the only access check in the package API that looks for permission to write to the linked repository. 🤷 It stands out as a possible mistake, but, not really relevant to why we can ignore repo-specific access tokens here.)
aahlenst marked this conversation as resolved
mfenniak force-pushed finegrained-pr7-semgrep from a274a3d662
All checks were successful
issue-labels / backporting (pull_request_target) Has been skipped
testing / semgrep/ci (pull_request) Successful in 18s
issue-labels / cascade (pull_request_target) Has been skipped
Integration tests for the release process / release-simulation (push) Successful in 5m34s
issue-labels / release-notes (pull_request_target) Has been skipped
requirements / merge-conditions (pull_request) Successful in 3s
testing / frontend-checks (pull_request) Successful in 1m21s
testing / backend-checks (pull_request) Successful in 3m37s
testing / test-unit (pull_request) Successful in 7m50s
testing / test-remote-cacher (redis) (pull_request) Successful in 2m24s
testing / test-remote-cacher (valkey) (pull_request) Successful in 3m12s
testing / test-remote-cacher (redict) (pull_request) Successful in 2m25s
testing / test-remote-cacher (garnet) (pull_request) Successful in 2m28s
testing / test-mysql (pull_request) Successful in 28m18s
testing / test-e2e (pull_request) Successful in 28m20s
testing / test-sqlite (pull_request) Successful in 34m23s
testing / test-pgsql (pull_request) Successful in 40m39s
testing / security-check (pull_request) Successful in 1m44s
to a8fef29b10
All checks were successful
issue-labels / release-notes (pull_request_target) Has been skipped
requirements / merge-conditions (pull_request) Successful in 2s
testing / backend-checks (pull_request) Successful in 4m0s
testing / frontend-checks (pull_request) Successful in 1m12s
testing / semgrep/ci (pull_request) Successful in 16s
testing / test-unit (pull_request) Successful in 7m12s
testing / test-remote-cacher (redis) (pull_request) Successful in 2m6s
testing / test-remote-cacher (valkey) (pull_request) Successful in 2m12s
testing / test-remote-cacher (redict) (pull_request) Successful in 2m14s
testing / test-remote-cacher (garnet) (pull_request) Successful in 2m18s
testing / test-e2e (pull_request) Successful in 22m20s
testing / test-mysql (pull_request) Successful in 24m3s
testing / test-sqlite (pull_request) Successful in 27m10s
testing / test-pgsql (pull_request) Successful in 32m15s
testing / security-check (pull_request) Successful in 57s
issue-labels / backporting (pull_request_target) Has been skipped
milestone / set (pull_request_target) Successful in 15s
2026-03-03 17:07:29 +01:00
Compare
aahlenst approved these changes 2026-03-03 17:17:19 +01:00
mfenniak merged commit 3d6acf5e8c into forgejo 2026-03-03 17:55:37 +01:00
mfenniak deleted branch finegrained-pr7-semgrep 2026-03-03 17:55:39 +01:00
Sign in to join this conversation.
No reviewers
No labels
arch
riscv64
backport/v1.19
backport/v1.20
backport/v1.21/forgejo
backport/v10.0/forgejo
backport/v11.0/forgejo
backport/v12.0/forgejo
backport/v13.0/forgejo
backport/v14.0/forgejo
backport/v7.0/forgejo
backport/v8.0/forgejo
backport/v9.0/forgejo
breaking
bug
bug
confirmed
bug
duplicate
bug
needs-more-info
bug
new-report
bug
reported-upstream
code/actions
code/api
code/auth
code/auth/faidp
code/auth/farp
code/email
code/federation
code/git
code/migrations
code/packages
code/wiki
database
MySQL
database
PostgreSQL
database
SQLite
dependency-upgrade
dependency
certmagic
dependency
chart.js
dependency
Chi
dependency
Chroma
dependency
citation.js
dependency
codespell
dependency
css-loader
dependency
devcontainers
dependency
dropzone
dependency
editorconfig-checker
dependency
elasticsearch
dependency
enmime
dependency
F3
dependency
ForgeFed
dependency
garage
dependency
Git
dependency
git-backporting
dependency
Gitea
dependency
gitignore
dependency
go-ap
dependency
go-enry
dependency
go-gitlab
dependency
Go-org
dependency
go-rpmutils
dependency
go-sql-driver mysql
dependency
go-swagger
dependency
go-version
dependency
go-webauthn
dependency
gocron
dependency
Golang
dependency
goldmark
dependency
goquery
dependency
Goth
dependency
grpc-go
dependency
happy-dom
dependency
Helm
dependency
image-spec
dependency
jsonschema
dependency
KaTeX
dependency
lint
dependency
MariaDB
dependency
Mermaid
dependency
minio-go
dependency
misspell
dependency
Monaco
dependency
PDFobject
dependency
playwright
dependency
postcss
dependency
postcss-plugins
dependency
pprof
dependency
prometheus client_golang
dependency
protobuf
dependency
relative-time-element
dependency
renovate
dependency
reply
dependency
ssh
dependency
swagger-ui
dependency
tailwind
dependency
temporal-polyfill
dependency
terminal-to-html
dependency
tests-only
dependency
text-expander-element
dependency
urfave
dependency
vfsgen
dependency
vite
dependency
Woodpecker CI
dependency
x tools
dependency
XORM
Discussion
duplicate
enhancement/feature
forgejo/accessibility
forgejo/branding
forgejo/ci
forgejo/commit-graph
forgejo/documentation
forgejo/furnace cleanup
forgejo/i18n
forgejo/interop
forgejo/moderation
forgejo/privacy
forgejo/release
forgejo/scaling
forgejo/security
forgejo/ui
Gain
High
Gain
Nice to have
Gain
Undefined
Gain
Very High
good first issue
i18n/backport-stable
impact
large
impact
medium
impact
small
impact
unknown
Incompatible license
issue
closed
issue
do-not-exist-yet
issue
open
manual test
Manually tested during feature freeze
OS
FreeBSD
OS
Linux
OS
macOS
OS
Windows
problem
QA
regression
release blocker
Release Cycle
Feature Freeze
release-blocker
v7.0
release-blocker
v7.0.1
release-blocker
v7.0.2
release-blocker
v7.0.3
release-blocker
v7.0.4
release-blocker
v8.0.0
release-blocker/v9.0.0
run-all-playwright-tests
run-end-to-end-tests
test
manual
test
needed
test
needs-help
test
not-needed
test
present
untested
User research - time-tracker
valuable code
worth a release-note
User research - Accessibility
User research - Blocked
User research - Community
User research - Config (instance)
User research - Errors
User research - Filters
User research - Future backlog
User research - Git workflow
User research - Labels
User research - Moderation
User research - Needs input
User research - Notifications/Dashboard
User research - Rendering
User research - Repo creation
User research - Repo units
User research - Security
User research - Settings (in-app)
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo/forgejo!11476
No description provided.