Skip to content
Release Of 28.2.0

Release Of 28.2.0

blog.gitea.com • October 18, 2026

We are excited to announce the release of Gitea 28.2.0 , the second maintenance release for the 28 series. It contains security fixes and a number of bug fixes for Actions, pull requests, authentication and packages. We strongly recommend that all users upgrade as soon as possible.

This release addresses the following security vulnerabilities. Please upgrade as soon as possible.

CVE-2026-109553 : SSH certificate principals were looked up among all stored public keys instead of only principal keys, so a certificate listing another user’s public key as a principal authenticated as that user when the trusted user CA accepts arbitrary principals. Fixed by #39839 / #39847 . Thanks to @DshtAnger for reporting the issue, and to @silverwind , @wxiaoguang and @bircni for the patch.

CVE-2026-104627 : The OpenID association callback in the security settings did not check that the logged-in user had started the linking, so an unsolicited assertion from an attacker-controlled OpenID provider could attach the attacker’s identity to a victim’s account and later be used to sign in as the victim. The callback now requires a short-lived state value bound to the user. Fixed by #39642 / #39744 . Thanks to @cyberlanc3r and @u2usvc for reporting the issue, and to @SHIVANSHGARG07 and @wxiaoguang for the patch.

CVE-2026-107686 : The web UI accepted reactions on locked issues and from users without write access, although the API refused them. Editing, deleting and reacting to issue content and attachments now one permission check in the web UI and the API. Fixed by #39839 / #39847 . Thanks to @hariprasanth9317-tech for reporting the issue, and to @silverwind , @wxiaoguang and @bircni for the patch.

CVE-2026-110494 : Adding attachments to a release did not reject attachments that were already linked to an issue or , so a user with release write access could expose the metadata of an issue attachment through a release and then rename or delete it. Fixed by #39839 / #39847 . Thanks to @manus-pi for reporting the issue, and to @silverwind , @wxiaoguang and @bircni for the patch.

CVE-2026-105661 : Requesting /{username}/-/repositories for an individual user instead of an organization caused a nil-pointer panic, so anonymous visitors could trigger errors on every request. The route now returns 404 for individual users. Fixed by #39839 / #39847 . Thanks to @kewmine , @tienpa99 and @gemstone-source for reporting the issue, and to @silverwind , @wxiaoguang and @bircni for the patch.

CVE-2026-110311 : Creating a draft release returned the attachments of the whole instance, including issue and attachments of repositories the caller could not read. Fixed by #39743 / #39752 . Thanks to @danielroe for reporting the issue, and to @wxiaoguang for the patch.

CVE-2026-105964 : The Actions artifact v4 API read the request body without a size limit, so a holder of a runner token could exhaust the memory of the server. The body is now limited to 1 MiB. Fixed by #39818 / #39822 . Thanks to @manus-pi and @N0K0 for reporting the issue, and to @SHIVANSHGARG07 for the patch.

CVE-2026-110324 : Sending a POST request to the profile of a private or limited user returned profile information to users who could not see that profile. This was fixed in 28.1.0 and is disclosed with this release. Fixed by #39501 / #39507 . Thanks to @Yanni8 for the analysis, and to @silverwind and @bircni for the patch.

CVE-2026-109844 : GET /api/v1/user/subscriptions returned metadata of watched private repositories after the user had lost access to them. This was fixed in 28.0.0 and 1.27.0 and is disclosed with this release. Fixed by #38321 / #38390 . Thanks to @manus-pi for reporting the issue, and to @bircni for the patch.

CVE-2026-107618 : The repository topics endpoint was not covered by the cross-origin protection, so a third-party site could change the topics of a repository on behalf of a repository administrator (CSRF). Fixed by #39839 / #39847 . Thanks to @bruhdev1290 for reporting the issue, and to @silverwind , @wxiaoguang and @bircni for the patch.

CVE-2026-97859 : Seven API routes under /api/v1/users/{username} (followers, following, starred and watched repositories, SSH and GPG keys) were missing the visibility check, so an authenticated user could read them for users with limited or private visibility. This was fixed in 28.0.0 and 1.27.3 and is disclosed with this release. Fixed by #39004 / #39039 . Thanks to @lukegranto23 , @KadirArslan , @DshtAnger , @DevNoScope , @gigioneggiando and @manus-pi for reporting the issue, and to @bircni for the patch.

CVE-2026-97204 : Deleting a label compared the repository ID against the organization ID of organization labels, so a user with write access to a repository could delete the labels of an organization with the same numeric ID. Labels are now deleted only within their own repository or organization. Fixed by #39743 / #39752 . Thanks to @N0K0 for reporting the issue, and to @wxiaoguang for the patch.

We are grateful to all the security researchers who responsibly disclosed these issues.

Accounts and authentication

Incoming email tokens of users who cannot sign in (inactive, prohibited or organizations) are rejected ( #39833 ), competing remember-me token rotations no longer log users out ( #39686 ), and WebAuthn accepts unsolicited client extension outputs from WebKit clients ( #39792 ).

A commit with an empty author email is no longer matched to a user ( #39777 ), email address validation is relaxed to what Go’s mail.ParseAddress accepts ( #39661 ), and OIDC discovery no longer advertises an unsupported id_token response type ( #39498 ).

The gitea-vscode OAuth2 application is pre-registered ( #39785 ), and users with “Only Email on Mention” still receive emails for the events of a custom repository watch ( #39652 ).

Folded block scalars in workflow files are kept intact ( #39787 ), invalid activity type patterns no longer panic event detection ( #39721 ), and out-of-range log cursors and unknown actor filters return proper errors instead of a 500 ( #39721 ).

Schedules are cleaned up correctly and follow a default branch switch ( #39740 ), and cancelled reusable workflow runs no longer get stuck in “cancelling” ( #39706 ).

Pull requests and Git

Pull requests whose recorded merge commit never reached the base repository are recovered ( #39831 ), and empty pull requests are not detected as manually merged ( #39807 ).

Review on unchanged lines show the correct code context ( #39799 ), and file names with non-ASCII characters are shown correctly in the diff file tree ( #39781 ).

Fetching remote commits skips writing the commit graph ( #39798 ), reflog expiry is left to Git’s defaults ( #39703 ), Git config values are matched exactly when syncing ( #39728 ), and LFS object IDs are validated before they are turned into file system paths ( #39762 ).

The go get URL uses the correct SSH scheme ( #39674 ), and the issue branch/tag dropdown can select a tag again ( #39747 ).

Packages, markup and UI

The former npm tarball URLs work again ( #39681 ), and the Debian installation values can be copied ( #39718 ).

srcset links of elements are resolved and proxied ( #39708 ), copying code from rendered blocks works again ( #39755 ), and display MathML has the correct spacing ( #39663 ).

Telegram webhook messages keep their line breaks ( #39650 ), the milestone page uses the correct template variable ( #39834 ), the change password page gets its websocket notification ( #39671 ), and a panic in the notification service no longer crashes Gitea ( #39835 ).

golang.org/x/net is updated to v0.60.0 to address CVE-2026-78659, a memory exhaustion in the HTTP/2 server caused by trailer headers ( #39695 ).

This release includes 39 merged pull requests , thanks to the amazing contributions from our community.

How to install or update

Download our pre-built binaries from the Gitea downloads page — make sure to select the version compatible with your platform. For a step-by-step guide on installation or upgrades, check out our installation documentation .

We would also like to thank all of our supporters on Open Collective who are helping to sustain us financially.

Looking for a seamless, hassle-free solution to manage your Git repositories? Discover Gitea Cloud — A fully-managed, scalable platform designed to streamline your development workflow.

(oauth) Pre-register a builtin OAuth2 application for gitea-vscode ( #39785 ) ( #39801 )

Allow custom watches to bypass on-mention email restriction ( #39652 ) ( #39837 )

Various bugs ( #39661 ) ( #39667 )

(markup) Display MathML has no space below it ( #39663 ) ( #39668 )

Correct websocket notification for change password page ( #39671 ) ( #39670 )

(webhook) Keep line breaks in Telegram rich messages ( #39650 ) ( #39677 )

Correct “go get” URL ssh scheme, fix form binding ( #39674 , #39528 ) ( #39676 )

OIDC discovery advertises unsupported id_token response_type ( #39498 ) ( #39689 )

(deps) Update module golang.org/x/net to v0.60.0 [security] ( #39695 ) ( #39701 )

(git) Leave reflog expiry to git’s defaults ( #39703 ) ( #39711 )

(actions) Settle cancelled reusable workflow runs stuck in cancelling ( #39706 ) ( #39717 )

(git) Match git config values exactly when syncing ( #39728 ) ( #39729 )

(actions) Harden log cursor, activity type and actor filter handling ( #39721 ) ( #39731 )

(packages) Copy selected Debian installation values ( #39718 ) ( #39734 )

(auth) Prevent competing remember-me token rotations ( #39686 ) ( #39688 )

(packages/npm) Restore former tarball URLs ( #39681 ) ( #39749 )

(issues) Allow selecting a tag in the issue Branch/Tag dropdown ( #39747 ) ( #39753 )

Validate “state” for OpenID ( #39642 ) ( #39744 )

Correct label deletion and release attachment load ( #39743 ) ( #39752 )

(markup) Resolve and proxy srcset links of elements ( #39708 ) ( #39756 )

(lfs) Validate OID before building filesystem object path ( #39762 ) ( #39766 )

(markup) Restore code copy newline strip and fix copying rendered blocks ( #39755 ) ( #39765 )

(user) Don’t match a commit with an empty author email to a user ( #39777 ) ( #39780 )

(gitdiff) Unquote C-quoted paths from git diff-tree --raw ( #39781 ) ( #39783 )

(actions) Fix schedule cleanup and default branch switch ( #39740 ) ( #39786 )

Skip commit-graph write when fetching remote commits ( #39798 )

(webauthn) Accept unsolicited client extension outputs from WebKit clients ( #39792 ) ( #39806 )

(pull) Fix code context of review on unchanged lines ( #39799 ) ( #39805 )

(pull) Don’t auto-detect empty pull requests as manually merged ( #39807 ) ( #39812 )

(actions) Keep folded block scalars intact across serialization ( #39787 ) ( #39817 )

(actions) Bound request body size in artifacts v4 twirp handlers ( #39818 ) ( #39822 )

Prevent Gitea from crashing by notification panic ( #39835 )

(pull) Recover PRs whose recorded merge commit never reached the base repo ( #39831 ) ( #39840 )

Use correct template variable on milestone page ( #39834 ) ( #39843 )

(mailer) Reject incoming email tokens of users who cannot sign in ( #39833 ) ( #39841 )

Add missing checks to several handlers and models ( #39839 ) ( #39847 )

Gitea 28.1.0 is released

Gitea 28.0.0 is released

bircni , TheFox0x7 — Sep 30, 2026

Gitea 1.27.3 is released

bircni — Aug 29, 2026

Gitea is open source. Star our GitHub repo, and join our community on Discord!

Stay up to date with all things Gitea