Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 275/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 01:07 UTC Customize Public modeDiscuss ChangeIntel on Discord

Gitea: Improper authorization on OAuth sign-in callback silently re-enables administrator-disabled accounts

Exact source revision recorded 24 Oct 2026 13:19:41 UTC. It does not establish the source's current position. Latest evidence.

osv · GHSA-g9g6-qhrc-p3qc

Published

### Summary The OAuth2 sign-in callback in Gitea 1.26.1 unconditionally re-enables a locally-disabled account whenever the user authenticates through a linked external identity provider, silently undoing any administrator-initiated `Disable Account` action and issuing a fresh authenticated session in the same response. Once a user has linked any external IdP, the administrator's disable toggle becomes non-binding — the user can re-enable themselves on demand by completing one OAuth callback, regaining full read and write access to their repositories, organizations, and access tokens. ### Details Improper Authorization is present on the `code` and `state` parameters of the `/user/oauth2/{source-name}/callback` endpoint in Gitea version 1.26.1. The handler `routers/web/auth/oauth.go::handleOAuth2SignIn` reads the local user's `IsActive` flag at lines 350-352 and, when it is `false`, sets `opts.IsActive = optional.Some(true)` before calling `user_service.UpdateUser` and immediately establishing a session. The active-state precondition that the request middleware `routers/web/web.go::verifyAuthWithOptions` enforces for every other request is therefore evaluated against the freshly-flipped row on the next request, so a site administrator's "disable user" action is silently undone the next time the user authenticates through any linked external identity provider. The root cause is that the callback path treats the local `IsActive` flag as stale bookkeeping to reconcile against the external identity, rather than as an authoritative administrative override. The local-credential sign-in path correctly renders `IsErrUserInactive` in the same condition; only the OAuth callback path flips the flag and proceeds. ### PoC 1. As a site administrator, configure an OAuth2 authentication source via `Site Administration -> Authentication Sources -> Add Authentication Source`. Any external provider works (a self-hosted Keycloak, an upstream Gitea acting as OIDC, GitHub, GitLab, Microsoft, Google). 2. Have a normal user (`alice` in the example) sign in through that source at least once. The callback creates the row in `external_login_user` linking alice's local account to the IdP identity. 3. As the site administrator, disable alice's account: `Site Administration -> User Accounts -> alice -> "Disable Account"`. Confirm the flag is set with the admin API. #### HTTP REQUEST ```http GET /api/v1/admin/users/alice HTTP/1.1 Host: <HOST> Authorization: token <ADMIN_TOKEN> Accept: application/json ``` #### HTTP RESPONSE ```http HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 {"id":2,"login":"alice","active":false,...} ``` 4. Have alice click "Sign in with <source-name>" on the Gitea login page and complete the OAuth dance with the IdP. The callback handler runs, observes `IsActive=false`, sets `opts.IsActive=true`, calls `UpdateUser`, and issues a session on the same response. Alice lands on `/`. 5. Re-read the same admin API endpoint and observe that `active` has flipped back to `true` without administrator action. #### HTTP REQUEST ```http GET /api/v1/admin/users/alice HTTP/1.1 Host: <HOST> Authorization: token <ADMIN_TOKEN> Accept: application/json ``` #### HTTP RESPONSE ```http HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 {"id":2,"login":"alice","active":true,...} ``` ### Impact Once a user has linked any external identity provider, the site administrator's "disable user" toggle becomes non-binding on that account: the user can re-enable themselves on demand by completing one OAuth callback, regaining full read and write access to their repositories, organizations, and tokens. In SSO-fronted Gitea deployments where the disable toggle is the documented incident-response action for compromised accounts or departed employees, this defeats the only short-term remediation available before the identity provider can revoke the underlying federated identity.

Source published
21 Jul 2026 21:48:48 UTC
Source modified
22 Jul 2026 21:11:29 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V4 · CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N

Publisher rating · HIGH

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 8 Nov 01:07 UTC · 275 of 275 readable · 273 fully read · documentation 469/469 current