## Detailed comments on security bug fixes

- [PR](https://codeberg.org/forgejo/forgejo/pulls/9071) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9081)): <!--number 9081 --><!--line 0 --><!--description Zml4OiB2YWxpZGF0ZSBDU1JGIG9uIG5vbi1zYWZlIG1ldGhvZHM=-->fix: validate CSRF on non-safe methods<!--description-->
  All PUT/DELETE routes in the web UI are validated to prevent a [cross site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery). Although all POST routes are validated with a CSRF token, some of the PUT/DELETE routes were missing this validation.
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9067) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9069)): <!--number 9069 --><!--line 0 --><!--description Zml4OiB1c2UgY3JlZGVudGlhbHMgaGVscGVycyBmb3IgZ2l0IGNsb25lcw==-->fix: use credential helpers for git clones<!--description-->
  When performing a `git clone` that requires credentials, they are temporarily stored in files and used with [Git credential](https://git-scm.com/docs/gitcredentials/2.50.0#_requesting_credentials). They were previously included in the URL that were readable by a user with shell access to the host running the Forgejo instance when, for instance, they ask for the list of process (`ps`).
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9073) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9096)): <!--number 9096 --><!--line 0 --><!--description Zml4OiBjb25zaXN0ZW50bHkgZW5mb3JjZSAyRkEgb24gT3BlbklEIDIuMA==-->fix: consistently enforce 2FA on OpenID 2.0<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9076) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9086)): <!--number 9086 --><!--line 0 --><!--description Zml4OiBkZWxldGUgb2xkIGF1dGggdG9rZW4gdXBvbiByZXBsYWNpbmcgcHJpbWFyeSBlbWFpbA==-->fix: delete old auth token upon replacing primary email<!--description-->
  When the primary email is changed before it is validated, the URL sent for validation purposes must be invalidated. It was previously possible use to delay use of the URL to validate the primary email and modify the primary email in the meantime. It allowed to validate the newer primary email using the older primary email, effectively bypassing validation.
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9070) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9079)): <!--number 9079 --><!--line 0 --><!--description Zml4OiByZXF1aXJlIHBhc3N3b3JkIGxvZ2luIGZvciBjcmVhdGlvbiBvZiBuZXcgdG9rZW4=-->fix: require password login for creation of new token<!--description-->
  Obtaining a [personal access token via the API](https://forgejo.org/docs/latest/user/api-usage/#generating-and-listing-api-tokens)  is no longer possible if the password used for basic authentication is an API token or an [OAuth2 token](https://forgejo.org/docs/latest/user/api-usage/#oauth2-provider): it has to be the user password. Such privilege escalation was only possible for tokens with write permissions to the user.
  This requirement is already enforced when API calls are made with an authorization header [as described in the documentation](https://forgejo.org/docs/latest/user/api-usage/#authentication), but it was not enforced with basic authentication. As a consequence it was possible for an API token with `write:user` permissions or an OAuth2 token to obtain a new token with a wider or identical scope.
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9075) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9084)): <!--number 9084 --><!--line 0 --><!--description Zml4OiBlbnN1cmUgR2V0VXNlckJ5RW1haWwgb25seSBjb25zaWRlcnMgdmFsaWRhdGVkIGVtYWlscw==-->fix: ensure GetUserByEmail only considers validated emails<!--description-->
  Only validated emails can be used to:
  
  -  assert if a signature can be trusted or,
  -  to assign comments, issues to an existing user during a migration 
  
  The emails that were not yet validated could previously used as if they were validated, incorrectly showing commits as trusted or assigning comments, issues to the user associated with this email during migrations.
  
  Existing migrations are not modified when they were incorrectly assigned to an email that is not validated. The trust status of all commit signatures will now show differently depending on the validation status of an email.
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9064) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9065)): <!--number 9065 --><!--line 0 --><!--description Zml4OiBkb24ndCBhbGxvdyBjcmVkZW50aWFscyBpbiBtaWdyYXRlL3B1c2ggbWlycm9yIFVSTA==-->fix: don't allow credentials in migrate/push mirror URL<!--description-->
  It is no longer possible to specify the user and password when providing a URL for migrating a repository, the fields dedicated to that purpose on the form must be used instead. This is to prevent that those credentials are displayed in the repository settings that are visible by the repository admins, in the case where the migration is a mirror.
- [PR](https://codeberg.org/forgejo/forgejo/pulls/9072) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9089)): <!--number 9089 --><!--line 0 --><!--description Zml4OiBvbmx5IHJlZGlyZWN0IHRvIGEgbmV3IG93bmVyIChvcmdhbml6YXRpb24gb3IgdXNlcikgaWYgdGhlIHVzZXIgaGFzIHBlcm1pc3Npb25zIHRvIHZpZXcgdGhlIG5ldyBvd25lcg==-->fix: only redirect to a new owner (organization or user) if the user has permissions to view the new owner<!--description-->

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Security bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9071) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9081)): <!--number 9081 --><!--line 0 --><!--description Zml4OiB2YWxpZGF0ZSBDU1JGIG9uIG5vbi1zYWZlIG1ldGhvZHM=-->fix: validate CSRF on non-safe methods<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9067) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9069)): <!--number 9069 --><!--line 0 --><!--description Zml4OiB1c2UgY3JlZGVudGlhbHMgaGVscGVycyBmb3IgZ2l0IGNsb25lcw==-->fix: use credential helpers for git clones<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9073) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9096)): <!--number 9096 --><!--line 0 --><!--description Zml4OiBjb25zaXN0ZW50bHkgZW5mb3JjZSAyRkEgb24gT3BlbklEIDIuMA==-->fix: consistently enforce 2FA on OpenID 2.0<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9076) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9086)): <!--number 9086 --><!--line 0 --><!--description Zml4OiBkZWxldGUgb2xkIGF1dGggdG9rZW4gdXBvbiByZXBsYWNpbmcgcHJpbWFyeSBlbWFpbA==-->fix: delete old auth token upon replacing primary email<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9070) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9079)): <!--number 9079 --><!--line 0 --><!--description Zml4OiByZXF1aXJlIHBhc3N3b3JkIGxvZ2luIGZvciBjcmVhdGlvbiBvZiBuZXcgdG9rZW4=-->fix: require password login for creation of new token<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9075) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9084)): <!--number 9084 --><!--line 0 --><!--description Zml4OiBlbnN1cmUgR2V0VXNlckJ5RW1haWwgb25seSBjb25zaWRlcnMgdmFsaWRhdGVkIGVtYWlscw==-->fix: ensure GetUserByEmail only considers validated emails<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9064) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9065)): <!--number 9065 --><!--line 0 --><!--description Zml4OiBkb24ndCBhbGxvdyBjcmVkZW50aWFscyBpbiBtaWdyYXRlL3B1c2ggbWlycm9yIFVSTA==-->fix: don't allow credentials in migrate/push mirror URL<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9072) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9089)): <!--number 9089 --><!--line 0 --><!--description Zml4OiBvbmx5IHJlZGlyZWN0IHRvIGEgbmV3IG93bmVyIChvcmdhbml6YXRpb24gb3IgdXNlcikgaWYgdGhlIHVzZXIgaGFzIHBlcm1pc3Npb25zIHRvIHZpZXcgdGhlIG5ldyBvd25lcg==-->fix: only redirect to a new owner (organization or user) if the user has permissions to view the new owner<!--description-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9000) ([backported](https://codeberg.org/forgejo/forgejo/pulls/9005)): <!--number 9005 --><!--line 0 --><!--description Zml4KGNvZGUtc2VhcmNoKTogZml4IGJyb2tlbiBwYWdpbmF0aW9uLg==-->fix(code-search): fix broken pagination.<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8678) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8974)): <!--number 8974 --><!--line 0 --><!--description Zml4OiBzdG9yZSBjb2RlIGNoYWxsZW5nZSBjb3JyZWN0bHkgaW4gc2Vzc2lvbg==-->fix: store code challenge correctly in session<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8864) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8884)): <!--number 8884 --><!--line 0 --><!--description Zml4OiBkZS1kdXBsaWNhdGUgRm9yZ2VqbyBBY3Rpb25zIGpvYiBuYW1lcyB3aGVuIG5lZWRlZA==-->fix: de-duplicate Forgejo Actions job names when needed<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8330) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8522)): <!--number 8522 --><!--line 0 --><!--description Zml4OiBsb2FkIE9sZE1pbGVzdG9uZSBiYXNlZCBvbiBPbGRNaWxlc3RvbmVJRCwgbm90IE1pbGVzdG9uZUlE-->fix: load OldMilestone based on OldMilestoneID, not MilestoneID<!--description-->
- Included for completeness but not user-facing (chores, etc.)
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/9031): <!--number 9031 --><!--line 0 --><!--description c3RvcmFnZSB0ZXN0OiByZWFkZXIgc2hvdWxkIG5vdCBiZSBjbG9zZWQgb24gc2F2ZQ==-->storage test: reader should not be closed on save<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8847) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8848)): <!--number 8848 --><!--line 0 --><!--description Zml4KHRlc3QpOiBUZXN0QWN0aW9uc0FydGlmYWN0T3ZlcndyaXRlIG5lZWRzIG9yZGVyZWQgcXVlcnkgZm9yIHBnc3Fs-->fix(test): TestActionsArtifactOverwrite needs ordered query for pgsql<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8845): <!--number 8845 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuNC4xICh2MTEuMC9mb3JnZWpvKQ==-->Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.4.1 (v11.0/forgejo)<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8811): <!--number 8811 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuNiAodjExLjAvZm9yZ2Vqbyk=-->Update dependency go to v1.24.6 (v11.0/forgejo)<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8814): <!--number 8814 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWNoaS9jaGkvdjUgdG8gdjUuMi4yICh2MTEuMC9mb3JnZWpvKQ==-->Update module github.com/go-chi/chi/v5 to v5.2.2 (v11.0/forgejo)<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8645): <!--number 8645 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuMy41ICh2MTEuMC9mb3JnZWpvKQ==-->Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.3.5 (v11.0/forgejo)<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8638) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8640)): <!--number 8640 --><!--line 0 --><!--description UmV2ZXJ0ICJmaXgoY2kpOiBwdWxsIHN0eWx1cyBmcm9tIGdpdGh1YjpzdHlsdXMvc3R5bHVzIzAuNTcuMCAoIzg2MjUpIg==-->Revert "fix(ci): pull stylus from github:stylus/stylus#0.57.0 (#8625)"<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8625) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8626)): <!--number 8626 --><!--line 0 --><!--description Zml4KGNpKTogcHVsbCBzdHlsdXMgZnJvbSBnaXRodWI6c3R5bHVzL3N0eWx1cyMwLjU3LjA=-->fix(ci): pull stylus from github:stylus/stylus#0.57.0<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8611) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8614)): <!--number 8614 --><!--line 0 --><!--description Y2hvcmU6IGRpc2FibGUgRTJFIHRlc3QgZm9yIHdlYmtpdA==-->chore: disable E2E test for webkit<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8530) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8531)): <!--number 8531 --><!--line 0 --><!--description Zml4KHBhY2thZ2VzKTogc2tpcCBhbm90aGVyIHN0YWNrIGZyYW1lIGZyb20gbG9nZ2luZw==-->fix(packages): skip another stack frame from logging<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8301) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8517)): <!--number 8517 --><!--line 0 --><!--description Y2hvcmU6IHVzZSBldmVudHVhbGx5IGZvciBteXNxbCBjb2xsYXRpb24gdGVzdA==-->chore: use eventually for mysql collation test<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8492) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8497)): <!--number 8497 --><!--line 0 --><!--description Zml4KGNvZGUtc2VhcmNoKTogSGlnaGxpZ2h0U2VhcmNoUmVzdWx0Q29kZSBzaG91bGQgY291bnQgdGhlIG51bWJlciBvZiBieXRlcyBhbmQgbm90IHRoZSBudW1iZXIgb2YgcnVuZXM=-->fix(code-search): HighlightSearchResultCode should count the number of bytes and not the number of runes<!--description-->
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8460) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8465)): <!--number 8465 --><!--line 0 --><!--description Y2hvcmU6IGRpc2FibGUgbWlzbWF0Y2hlZCByb290IFVSTCBlMmUgdGVzdCBmb3Igc2FmYXJp-->chore: disable mismatched root URL e2e test for safari<!--description-->
<!--end release-notes-assistant-->
