Advisories for Golang/Code.gitea.io/Gitea package

2026

Gitea: Webhook Authorization Header Returned in Plaintext via API

The ToHook() function in services/webhook/general.go decrypts the webhook's HeaderAuthorizationEncrypted field and returns the plaintext authorization header in the API response. Any repository admin can read the full plaintext value of webhook authorization headers (Bearer tokens, Basic auth credentials, API keys) set by other admins. The authorization header is stored encrypted in the database using the server's SecretKey, but ToHook() decrypts it before serializing it into the API response — converting …

Gitea: Unbounded Arch package file metadata can cause resource amplification in Gitea package uploads

Hello Gitea Security Team, Thank you for your continued work on Gitea. I would like to responsibly report a potential availability-impact issue that I observed in Gitea’s Arch package registry implementation. During local testing, I noticed that Gitea records non-dot regular file entries from an uploaded Arch package archive into package file metadata. I could not identify an explicit limit on the number of recorded file entries or on the …

Gitea: Unauthorized Access to Labels of Private Organizations

Gitea 1.26.2 does not properly enforce organization visibility restrictions on organization label read endpoints. A user without access to a private organization can retrieve labels belonging to that organization through the Organization Labels API. As a result, label metadata intended to be restricted to organization members may be disclosed. The issue is limited to unauthorized read access. No unauthorized modification of labels was observed.

Gitea: Unauthenticated ReDoS via CODEOWNERS pattern matching allows denial of service

This issue has been found by a security agent and review by myself. Gitea's CODEOWNERS feature uses the regexp2 library to match file paths against ownership rules. User-supplied patterns are passed directly to regexp2.Compile with no sanitisation and no match timeout. This allows an attacker to write a pattern that causes the regex engine to backtrack exponentially when evaluated against a crafted file path.

Gitea: Two SSRF findings

Gitea guards outbound HTTP from webhooks and repo migration with net.Dialer.Control, the correct hook point. The IP classifier behind it misses ten address families, of which CGNAT (100.64.0.0/10) is the practically important one because it is plain IPv4 and is used today by Tailscale, AWS VPC secondary CIDRs, and several Kubernetes pod-CIDR conventions. Any logged-in user can create a webhook pointing at an internal CGNAT host. The full HTTP response …

Gitea: TOTP TOCTOU race on web 2FA paths + missing replay check on Basic-Auth `X-Gitea-OTP` surface

I'm reporting two related TOTP one-time-use defects in Gitea that survive the CVE-2021-45331 fix. The 2018 fix (PR #3878) introduced the TwoFactor.LastUsedPasscode field and added an in-memory inequality check on the web 2FA login path. That check works correctly in the single-request case, but it leaves two follow-up gaps: A TOCTOU race on the web surfaces (Defect 1). The read-validate-check-save sequence against the two_factor row is not atomic. Two parallel …

Gitea: Token public-only scope bypassed on Limited-visibility owners (Repository + Package categories) — residual after CVE-2026-25714 / PR #37118

After PR #37118 / CVE-2026-25714 (fix: Unify public-only token filtering in API queries and repo access checks, merged 2026-05-18, backport #37773 to 1.26.2 — the May 2026 unification pass for public-only token filtering, reporter Medoedus per the 1.26.2 release notes), the public-only PAT scope is still bypassable on Repository and Package scope categories when the owner's Visibility = Limited (instance-internal). The sibling Org / User / ActivityPub cases in the …

Gitea: SSRF via Migration Asset Downloads Bypasses hostmatcher — Reads Internal Files and Cloud Metadata

Gitea has robust SSRF protection via hostmatcher.NewDialContext() for webhook and migration clone URLs, which validates resolved IPs at the TCP dial level. However, three code paths use raw http.Get() (Go's DefaultClient) which completely bypasses this protection, enabling SSRF to internal services and local file read via the file:// scheme.

Gitea: SSRF via HTTP Redirect in Repository Migration

Gitea 1.25.4 validates the initial URL provided to the repository migration endpoint (POST /api/v1/repos/migrate) and correctly blocks requests to internal addresses like 127.0.0.1 or RFC1918 ranges. However, if the initial URL points to an attacker-controlled server that responds with an HTTP 302 redirect to an internal address, Gitea follows the redirect without performing a second validation. This allows a low-privilege user to reach internal services through Gitea as a proxy.

Gitea: SSRF in restore-repo via unsanitized pull_request.yml Head.CloneURL

Gitea's restore-repo CLI command restores a repository from a dump directory/archive. When parsing pull_request.yml from that dump, the Head.CloneURL field is used to add a git remote and fetch from it with no validation, because the safety check that's supposed to guard it (CheckAndEnsureSafePR) is called with an empty commonCloneBaseURL, which silently disables it. This lets a malicious dump make the Gitea server execute git fetch against an attacker-chosen URL …

Gitea: RSS/Atom feed handlers bypass API-token scope & public-only confinement (incomplete fix of #37698)

Gitea's RSS/Atom feed handlers accept API-token Basic auth but perform no token-scope or public-only enforcement. A personal access token that is correctly blocked (HTTP 403) from a private repository on /raw, /media, /archive, and /releases/download/… — because it is marked public-only or lacks the repository scope category — still returns that repository's private content through the feed routes. This is a token-confinement bypass and appears to be an incomplete fix …

Gitea: Repository Visibility Manipulation via Git Push Options

Gitea's post-receive git hook handler processes git push options — key-value pairs transmitted by a client during git push using the -o flag. Two undocumented push options, repo.private and repo.template, allow any user with repository owner or admin-collaborator access to toggle the visibility (private/public) and template status of a repository as a side effect of a normal git push. This capability was originally intended solely for the "push-to-create" feature (automatically …

Gitea: Repository migration SSRF via multi-answer DNS allow-list bypass

Gitea's repository migration URL validation can be bypassed when a migration hostname resolves to multiple IP addresses. The validation logic accepts the destination if any resolved IP is allowed, even if another resolved IP is loopback, private, or otherwise blocked. The later git clone operation resolves the hostname again outside of that validation decision, so it can connect to the internal address. An authenticated low-privilege user who can create repository …

Gitea: Repository Migration Follows Git HTTP Redirects After URL Allow/Block Validation, Enabling Internal Git Repository Exfiltration

Gitea validates the user-supplied repository migration URL, but the actual clone and later mirror fetch operations are performed by the Git command-line client without disabling HTTP redirects. Git's default http.followRedirects=initial follows the first redirect and then uses the redirected URL as the base for later repository object requests. This creates a URL-policy bypass, SSRF, and repository exfiltration primitive. A low-privileged authenticated user can submit an allowed public Git URL that …

Gitea: Release attachment extension allowlist bypass via web release edit form (variant of CVE-2025-68939)

The web handler EditReleasePost (routers/web/repo/release.go) reads form fields with prefix attachment-edit-{uuid} into a map[uuid]newName, passes that map to release_service.UpdateRelease, which writes the new name to the database via repo_model.UpdateAttachmentByUUID WITHOUT calling upload.Verify against setting.Repository.Release.AllowedTypes. The parent CVE-2025-68939 fix (PR #32151) added the equivalent upload.Verify call on the API edit endpoints via attachment_service.UpdateAttachment. The web release edit path was not updated. A user with repository write permission can rename any existing …

Gitea: Public-only repository tokens can update private PR head branches

Gitea allows a public-only,write:repository token to update a private pull request head branch through a public base repository route. The vulnerable endpoint is: POST /api/v1/repos/{public-owner}/{public-repo}/pulls/{index}/update Gitea checks the token's public-only restriction against the route repository, which is the public base repository. UpdatePullRequest() then authorizes the pull request head repository with ordinary user RBAC and calls the pull update service. If the head repository is private, the active token's public-only restriction …

Gitea: Privilege Escalation via Access Token Scope Escalation in API

Gitea's API endpoint for creating Personal Access Tokens (POST /users/{username}/tokens) is protected by a middleware (reqBasicOrRevProxyAuth) that is intended to require password-based authentication, preventing a compromised token from being used to mint new ones. However, when a token is passed in the Authorization: Basic <token>:x-oauth-basic format, the Basic auth handler validates it and sets AuthedMethod="basic", causing IsBasicAuth=true and fooling the middleware into passing the request. Once past the guard, the …

Gitea: Private Repository Metadata Remains Accessible After Access Revocation

A user who previously had access to a private repository can continue to obtain repository metadata through GET /api/v1/user/starred after their access to the repository has been revoked. After a collaborator is removed from a private repository, direct access to the repository is correctly denied. However, the repository may still appear in the user's starred repository list, and the endpoint continues to return repository metadata. Changes made to that metadata …

Gitea: Personal access token scope enforcement bypass on the repository home page (`GET /{owner}/{repo}`) discloses private repository contents

A personal access token (PAT) or OAuth2 token that does not carry the repository scope or that is public-only is correctly rejected (HTTP 403) by the recently hardened web content routes (archive download, raw/media file download, and repository RSS/Atom feeds). However, the repository home page route GET /{owner}/{repo} (handler repo.Home) serves the private repository's rendered README, root file/directory tree, description, language statistics, license, and latest-release information to that same token. …

Gitea: Permanent Fork PR Workflow Approval Gate Bypass

Gitea Actions enforces an approval gate on workflow runs triggered by fork pull requests, so that an untrusted contributor cannot execute arbitrary workflow YAML on the maintainer's runner infrastructure without explicit consent. The gate is implemented by ifNeedApproval() in services/actions/notifier_helper.go. Its final clause skips the gate whenever the triggering user has any previously-approved run in the same repository: // services/actions/notifier_helper.go:423-433 if count, err := db.Count[actions_model.ActionRun](ctx, actions_model.FindRunOptions{ RepoID: repo.ID, TriggerUserID: user.ID, …

Gitea: ParseAcceptLanguage quadratic-time DoS via Locale middleware on unauthenticated requests

The Locale middleware that runs in front of every unauthenticated request calls golang.org/x/text/language.ParseAcceptLanguage on the raw Accept-Language header without imposing a size or shape filter. The underlying parser has quadratic-time behaviour on long lists of malformed language tags. The CVE-2022-32149 guard that golang.org/x/text added in v0.3.8 caps the number of - characters in the input at 1000, but it does not cap _ characters even though the parser's internal scanner …

Gitea: OIDC userinfo Endpoint Returns Identity Claims Without Enforcing API Token Scopes

The OIDC userinfo endpoint (GET /login/oauth/userinfo) accepts Gitea API tokens as bearer credentials but does not enforce API token scopes before returning identity claims. A personal access token scoped only to read:misc can successfully retrieve user information from the OIDC userinfo endpoint, even though the same token is denied access to user-related REST API endpoints that enforce scope checks. As a result, identity information remains accessible through the OIDC endpoint …

Gitea: OAuth2 sign-in reactivates an administrator-deactivated account on auth sources without refresh tokens (incomplete fix of #38009)

Gitea's OAuth2 sign-in callback reactivates a deactivated user account (IsActive=false) when the user signs in through an authentication source that does not issue refresh tokens (notably GitHub, and any OIDC/OAuth2 source configured without offline_access). PR #38009 added a gate intended to reactivate users only when the OAuth2 auto-sync cron had disabled them, using "the stored refresh token is empty" as the signal. That signal is wrong: for sources that never …

Gitea: OAuth token introspection returns metadata of tokens issued to other clients (RFC 7662 section 4 violation)

Any authenticated OAuth client can call /login/oauth/introspect with another client's access or refresh token in the body and learn: active (true or false). A token-validity oracle that survives across application boundaries without consuming or "using" the token. scope. The scope of the token. username. The user the token belongs to. iss, sub, aud. Standard JWT registered claims. aud reveals the issuing client_id, making it obvious to the introspecting client that …

Gitea: Internal API HTTP client hardcodes InsecureSkipVerify:true with no config override

Summary Gitea's internal API HTTP client (modules/private/internal.go) hardcodes TLSClientConfig.InsecureSkipVerify = true with no configuration override. It is the only outbound TLS client in the codebase that cannot be made to verify its peer's certificate — webhook, migrations, MinIO, LDAP, SMTP, Redis and incoming-mail all expose a secure-by-default SkipVerify toggle, this one does not. When an operator configures internal communication over HTTPS to a non-loopback target (LOCAL_ROOT_URL=https:/// in a split-host / …

Gitea: Incomplete SSRF Protection in Webhook and Migration Allow-list Default Filter

Gitea's default SSRF allow-list (MatchBuiltinExternal, used by both webhook delivery and repository migrations) relies on Go's standard library net.IP.IsPrivate(), which only covers RFC 1918 and RFC 4193. As a result, several IP ranges commonly used for cloud metadata services, internal networks, and IPv6 transition mechanisms are not blocked, allowing authenticated users to send HTTP requests to those destinations and read the responses via the webhook history UI.

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

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 …

Gitea: GHSA-8fwc-qjw5-rvgp ClearRepoWatches fix not applied to API EditRepo path — sister code path retains stale watches on public->private

GHSA-8fwc-qjw5-rvgp ("Gitea may send release notification emails for private repositories to users whose access has been revoked", fix in PR #36319 / commit 8a98ac22) added repo_model.ClearRepoWatches as a defense for the state transition public→private. The cleanup was wired into services/repository/repository.go::MakeRepoPrivate only. The sister helper services/repository/repository.go::updateRepository — which is the function used by the API path PATCH /api/v1/repos/{owner}/{repo} — was not patched and still calls ClearRepoStars only. As a result, when …

Gitea: Fork Synchronization Continues After Parent Repository Changes from Public to Private

The POST /api/v1/repos/{owner}/{repo}/merge-upstream endpoint continues to synchronize commits from a parent repository after the parent repository has been changed from public to private. A fork created while the parent repository was public can still receive commits made after the parent repository becomes private. As a result, content added during the private period becomes available through the fork repository after synchronization.

Gitea: draft release attachment disclosure via missing web authorization

Gitea's draft-release access control is enforced only on the API release endpoints (/api/v1/repos/{owner}/{repo}/releases/{id} and its /assets/… sub-routes) but not on the web-level UUID-based attachment endpoints (/attachments/{uuid}, /{owner}/{repo}/attachments/{uuid}, /{owner}/{repo}/releases/attachments/{uuid}). Anyone (including unauthenticated callers) who has, learns, or otherwise obtains the UUID of an attachment belonging to a draft release can download its full contents, despite the draft release itself being correctly hidden from listings and direct-by-ID API lookups. The browser_download_url field …

Gitea: Denial of Service via Unbounded io.ReadAll in NPM Package Tag Endpoint

An unbounded io.ReadAll(ctx.Req.Body) call in the NPM package tag API endpoint allows any authenticated user to crash the Gitea server by sending a single large HTTP request. The request body is read entirely into memory with no size limit, causing an Out-of-Memory (OOM) kill. With concurrent requests, the attack produces a persistent denial of service that survives automatic restarts.

Gitea: Denial of Service (CPU & Memory Exhaustion) via O(N^2) String Concatenation in Debian Package Upload

Gitea's Debian package registry parser contains an unbounded decompression vulnerability in ParseControlFile. When processing an uploaded .deb file, the parser decompresses control.tar.gz and copies the entire uncompressed stream into a strings.Builder via a TeeReader, with no limit on how much data is read. Because DEFLATE compression can achieve ratios exceeding 100:1 on repetitive input, an attacker can craft an 83 MB .deb payload that expands to over 16 GB during …

Gitea: Cross-repository label-ID enumeration oracle via unscoped DeleteIssueLabel API

The API endpoint DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} loads the label by ID with a global, unscoped lookup and never verifies the label belongs to the URL's repository (or its owning organization). Because the response status differs by whether the label ID exists anywhere on the instance (204) versus not (422), an authenticated user can use the endpoint as a cross-repository label-ID existence / enumeration oracle, including for labels in repositories and organizations …

Gitea: Cross-repository issue/comment attachment re-linking can expose private attachment content

Gitea's issue and comment attachment update paths accept attachment UUIDs without verifying that each attachment belongs to the target issue/comment repository. If an authenticated attacker knows a victim attachment UUID, they can re-link that attachment to an attacker-controlled issue or comment, causing later attachment access checks to use the attacker's repository authorization context. Full HTTP/E2E observation: A local Gitea server was started with an isolated SQLite database. A victim user …

Gitea: Cross-Repo Information Disclosure via Org-Level Actions Run/Job APIs

The org-level Actions REST endpoints GET /api/v1/orgs/{org}/actions/runs GET /api/v1/orgs/{org}/actions/jobs are gated only by reqOrgMembership() + reqToken(). They then call shared.ListRuns(ctx, ctx.Org.Organization.ID, 0) / shared.ListJobs(ctx, ctx.Org.Organization.ID, 0, 0, nil), which selects every action_run / action_run_job row whose repository belongs to the org — with no per-repository ACL check. Result: any user who is a member of an organization can enumerate workflow runs and jobs from every repository in that org, including: …

Gitea: Cached Per-Branch Permission Check in Pre-Receive Hook Allows Full Repository Write

The pre-receive hook in Gitea evaluates the CanMaintainerWriteToBranch permission only once per git push session and caches the result for all subsequent refs in the same batch. An attacker who has a legitimate per-branch write grant (e.g., via an open pull request with "Allow edits from maintainers" enabled) can batch-push that branch together with any other ref. The cached true from the first ref is reused for all following refs, …

Gitea: Branch Protection Bypass via PR Retargeting Preserves Stale `official` Approval Flag

Gitea does not re-evaluate the official flag on existing pull request reviews when a PR's target branch is changed. An attacker with write access to a repository can obtain an official: true approval on a PR targeting an unprotected branch, then retarget the PR to a protected branch (e.g., master). The approval, which would have been official: false if submitted against the protected branch, is preserved and satisfies the protected …

Gitea: Blind SSRF in OAuth2 avatar synchronization via unvalidated OIDC picture claim

When [oauth2_client] UPDATE_AVATAR = true is enabled, Gitea fetches the avatar URL received from an OAuth2/OIDC provider using Go's default HTTP client. The URL comes from the user's OAuth/OIDC avatar value, commonly the OIDC picture claim. The affected code path calls http.Get(url) without applying outbound host or IP restrictions. A low-privileged user who can influence their own picture claim under an already-configured OAuth2/OIDC source can cause the Gitea server to …

Gitea: API Fork Endpoint Authorization Bypass Allows Organization Members to Bypass Repository Creation Restrictions

The API endpoint used to fork repositories into organizations performs a weaker authorization check than the corresponding web UI and other repository creation endpoints. When a repository is forked into an organization through the API, the endpoint only verifies that the user is an organization member (IsOrgMember()), but does not verify whether the user is allowed to create repositories in that organization (CanCreateOrgRepo()). As a result, organization members belonging to …

Gitea: API access token scope enforcement bypass on repository RSS/Atom feed endpoints leaks private repository commit data

A Gitea personal access token (PAT) restricted to a non-repository scope (e.g. read:issue) can read the commit history of any private repository the token owner can access, via the repository RSS/Atom feed endpoints. The same token is correctly denied (403) on /raw, /media, /archive, and the contents API. It leaks commit SHAs, full commit messages (which frequently contain secrets and internal context), and committer name + email.

Gitea SSH Key Parser Denial of Service

Gitea's SSH key ingestion endpoint accepts keys in RFC 4716 (SSH2) format and normalises them before storage. The normalisation function contains an O(N²) string concatenation loop with no input size limit, meaning a single malicious key submission can force the server to perform an amount of work that grows quadratically with the size of the input. Any authenticated user can exploit this to exhaust the server's CPU and memory, taking …

Gitea LFS Deploy-Key Privilege Escalation

Gitea's LFS server (services/lfs/server.go:268) uses the UserID embedded in an LFS JWT to make cross-repository authorization decisions via LFSObjectAccessible(). This would be safe if the JWT UserID always matched the actual requesting principal — but for deploy keys, routers/private/serv.go:275 sets UserID = repo.OwnerID instead of any identity representing the deploy key itself. As a result, an attacker who holds a write deploy key for any single repo owned by a …

Gitea Docker image: `REVERSE_PROXY_TRUSTED_PROXIES = *` default lets any source IP impersonate any user via `X-WEBAUTH-USER`

The Gitea Docker images ship an app.ini template that hard-codes: REVERSE_PROXY_TRUSTED_PROXIES = * The documented default for this setting, in custom/conf/app.example.ini, is 127.0.0.0/8,::1/128, i.e. only loopback is trusted. When an admin enables ENABLE_REVERSE_PROXY_AUTHENTICATION = true to put Gitea behind an authenticating reverse proxy and leaves the trusted-proxies setting at "the default", they expect only the proxy's loopback connection to inject identity. The Docker image instead trusts X-WEBAUTH-USER from any source …

Gitea CVE-2026-20800 sibling endpoints not covered: revoked user still reads private repo objects via `/api/v1/user/starred` and private issue titles via `/api/v1/user/times`

CVE-2026-20800 fixed private-info leakage to revoked users only for the notification endpoint. Two sibling endpoints that return data keyed on the caller's own relationship still do not re-check repo access at output time: GET /api/v1/user/starred — getStarredRepos() computes a per-repo permission but still lists every starred repo (no filtering), so the full repo object (full_name, private, clone_url, ssh_url) of a now-inaccessible private repo is returned. GET /api/v1/user/times — ListMyTrackedTimes() queries …

Gitea Actions Artifacts V4 signed URL HMAC ambiguity allows cross-repository artifact read and cross-task upload-state write

Gitea Actions Artifacts V4 signed upload/download URLs can be rewritten to access a different running task and repository context while preserving the original HMAC signature. An attacker with permission to run a Gitea Actions job can turn a signed URL for an attacker-controlled artifact into a URL that reads artifacts from another task context, or writes attacker-controlled data into another task's artifact upload staging context, including in a private repository. …

Gitea: Stored XSS via glTF `extensionsRequired` in Gitea 3D File Viewer

Me again. Gitea's built-in 3D file viewer (powered by Online3DViewer) is vulnerable to stored cross-site scripting (XSS) through crafted .gltf files. When a glTF file declares an unsupported required extension, Online3DViewer generates an error message containing the extension name and Gitea inserts it into the DOM using innerHTML without sanitization. An attacker who can push a .gltf file to any repository can execute arbitrary JavaScript in the context of any …

Gitea: Public-only tokens bypass private-resource restrictions on `/api/v1/user` self routes

Many authenticated self routes under /api/v1/user/… do not enforce the public-only token restriction. As a result, a token or OAuth grant marked public-only, but otherwise carrying the route-required read/write scope category, can access or modify private account resources through self routes. The canonical private-user endpoint correctly rejects the same tokens, for example GET /api/v1/users/{privateUser} returns 403. The bypass exists because the generic /api/v1/user route group requires user scope and reqToken(), …

Gitea: API Fork Missing CanCreateOrgRepo Check Allows Org Secret Exfiltration

The API endpoint POST /api/v1/repos/{owner}/{repo}/forks only checks IsOrgMember() when a user forks a repository into an organization, but does not check CanCreateOrgRepo(). The web UI fork handler correctly checks both. This allows a read-only organization member — in a team with can_create_org_repo=false — to create repositories in the organization namespace via the API. The attacker receives full admin permissions on the forked repository, can enable Actions, push arbitrary workflow files, …

Gitea: Token scope bypass on web archive download endpoint

PR #37698 added checkDownloadTokenScope to /raw/, /media/, and attachment download web endpoints. The /archive/* endpoint (repo.Download in routers/web/repo/repo.go:372) was not included in the fix. This endpoint accepts OAuth2 tokens via webAuth.AllowOAuth2 (registered at routers/web/web.go:1649-1652) but does not call checkDownloadTokenScope or CheckRepoScopedToken. A personal access token with any non-repository scope (e.g., read:issue or read:misc) can download full repository archives (zip/tar.gz) of private repositories the token owner has access to.

Gitea: OAuth2 access token scope enforcement bypass via HTTP Basic authentication

Gitea fails to enforce OAuth2 access token scopes when the token is submitted via HTTP Basic authentication instead of a Bearer token. An OAuth2 application granted only read:user can use the same token as Authorization: Basic base64(<token>:x-oauth-basic) and perform write actions, including modifying profiles, adding email addresses, creating repositories, and deleting repositories as the authorizing user.

Gitea: Missing repository-unit authorization on issue-template API endpoints

Three Gitea API endpoints — GET /repos/{owner}/{repo}/issue_templates, GET /repos/{owner}/{repo}/issue_config and GET /repos/{owner}/{repo}/issue_config/validate — read files from the repository's Code default branch (.gitea/ISSUE_TEMPLATE/* and issue_config.yaml) and return their contents, but are registered without the reqRepoReader(unit.TypeCode) authorization middleware that every sibling Code-tree endpoint in the same route group carries. A user who has access to a private repository through any single repository unit (for example an organization team granted only the Issues …

Gitea: Git Smart HTTP Skips Repository Token Scopes for Bearer Tokens

Gitea v1.26.1 enforces repository-scoped access-token permissions on repository operations. In the Git Smart HTTP path, however, this check runs only when the token is presented via HTTP Basic authentication — CheckRepoScopedToken() returns early unless ctx.IsBasicAuth is true — so the same token sent as Authorization: Bearer <token> bypasses the scope check entirely. As a result, a PAT or OAuth2 token presented as a Bearer credential can clone or fetch private …

2025
2024
2023
2022

Gitea allowed assignment of private issues

In Gitea before 1.16.9, it was possible for users to add existing issues to projects. Due to improper access controls, an attacker could assign any issue to any project in Gitea (there was no permission check for fetching the issue). As a result, the attacker would get access to private issue titles.

Gitea Arbitrary File Delete Vulnerability

Gitea version 1.6.2 and earlier contains a Incorrect Access Control vulnerability in Delete/Edit file functionallity that can result in the attacker deleting files outside the repository he/she has access to. This attack appears to be exploitable via the attacker must get write access to "any" repository including self-created ones. This vulnerability appears to have been fixed in 1.6.3, 1.7.0-rc2.

Session Fixation

Gitea before 1.5.4 allows remote code execution because it does not properly validate session IDs. This is related to session ID handling in the go-macaron/session code for Macaron.

Incomplete Cleanup

An issue exsits in Gitea through 1.15.7, which could let a malicious user gain privileges due to client side cookies not being deleted and the session remains valid on the server side for reuse.

Improper Authentication

An Authentication Bypass vulnerability exists in Gitea before 1.5.0, which could let a malicious user gain privileges. If captured, the TOTP code for the 2FA can be submitted correctly more than once.

2021