← Back to Feed CACHED · 2026-09-21 08:50:46 · CACHE_KEY tenable:304689
tenable:304689 · CWE-400 · Disclosed 2026-03-27

Grafana 8.1.0 < 11.6.14 / 12.0.0 < 12.1.10 / 12.2.0 < 12.2.8 /...

ASSESSED — NOISGATE
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Like handing every office visitor a button that reboots the lobby TV — annoying, not dangerous

CVE-2026-28375 is an uncontrolled resource consumption flaw (CWE-400 / CWE-770) in Grafana's built-in TestData datasource, a core plugin that ships enabled in every Grafana installation since version 8.1.0. Any authenticated user — even one with the lowest Viewer role — can craft a query against the testdata datasource that triggers unbounded memory allocations, causing the Grafana server process to hit an OOM condition and crash. Affected version ranges are massive: 8.1.0 through 11.6.13, 12.0.0 through 12.1.9, 12.2.0 through 12.2.7, 12.3.0 through 12.3.5, and 12.4.0 through 12.4.1. Fixed in 11.6.14, 12.1.10, 12.2.8, 12.3.6, and 12.4.2.

Grafana's own MEDIUM / 6.5 rating is directionally correct but generous at the score level. The CVSS vector AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H mechanically scores the availability impact as High, but ignores that Grafana processes typically restart within seconds under systemd or container orchestration, making the crash self-healing in most production deployments. There is no confidentiality or integrity impact whatsoever — no data leaks, no code execution, no lateral movement. Tenable's own VPR of 3.0 (Low, 24th percentile) reflects this reality. The EPSS probability is 0.38%, there are no public PoCs, no KEV listing, and zero observed in-the-wild exploitation. We hold the MEDIUM band but compress the score to 5.0 to reflect practical recoverability and the authentication gate.

"Auth-required DoS in Grafana testdata datasource — recoverable crash, no data risk, patch in cycle"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain authenticated Grafana session

The attacker needs a valid Grafana login — any role including Viewer suffices. In enterprises, Grafana is often federated via LDAP, OAuth/OIDC, or SAML, meaning any employee or contractor with SSO access to the monitoring stack has a session. Alternatively, default credentials (admin/admin) on forgotten dev instances provide access.
Conditions required:
  • Valid Grafana credentials or SSO session
  • Network access to Grafana HTTP(S) endpoint (typically port 3000)
Where this breaks in practice:
  • Most enterprise Grafana instances sit on internal networks behind VPN or zero-trust gateways
  • Internet-exposed instances (~46K on Shodan) are a minority and increasingly protected by WAF or IP allowlists
  • MFA on SSO reduces credential-stuffing viability
Detection/coverage: Failed login attempts visible in Grafana server logs and IdP audit logs. Shodan/Censys can identify external exposure.
STEP 02

Craft unbounded testdata query

The attacker issues a query to the built-in grafana-testdata-datasource with parameters that cause unbounded memory allocation. The testdata datasource is a core plugin — no additional configuration or plugin installation is required. The exact payload involves requesting a scenario that generates an arbitrarily large in-memory dataset. No specialized tooling is needed; the Grafana Explore UI or a direct API call to /api/ds/query suffices.
Conditions required:
  • Testdata datasource accessible (default: yes, core plugin)
  • User has permission to execute datasource queries (Viewer role or above)
Where this breaks in practice:
  • Organizations that have hardened Grafana may have restricted datasource query permissions via RBAC (Grafana Enterprise feature)
  • Rate limiting or query timeout configurations can bound the allocation window
  • Resource limits (cgroups, Kubernetes memory limits) will OOM-kill the container but prevent host-wide impact
Detection/coverage: Query audit logs (if enabled) would show testdata queries with unusual parameters. Resource monitoring (Prometheus metrics for Grafana process RSS) would show memory spike.
STEP 03

Grafana process crashes (OOM)

The unbounded allocation exhausts available memory. On bare-metal or VM deployments, the Linux OOM killer terminates the Grafana process. On Kubernetes, the pod exceeds its memory limit and is evicted. In either case, the service is temporarily unavailable to all users. Dashboards, alerts configured in Grafana Alerting, and embedded panels all go dark until the process restarts.
Conditions required:
  • Grafana process memory is not bounded by cgroup/container limits below the crash threshold
Where this breaks in practice:
  • systemd Restart=always or Kubernetes restartPolicy: Always brings the service back in seconds
  • Grafana Alerting evaluation may be handled by a separate process or external Alertmanager, limiting blast radius
  • HA deployments behind a load balancer survive a single-node crash
Detection/coverage: Process restart events in journald/container runtime logs. Grafana health endpoint (/api/health) returns 503 during downtime. Uptime monitors and synthetic checks catch this immediately.
STEP 04

Temporary observability blindness

While Grafana is restarting, operators lose access to dashboards. If the attacker repeatedly sends the payload, they can keep crashing the instance — but each crash requires a new authenticated request and the restart window is typically 2-10 seconds. Sustained denial requires active, ongoing exploitation. The attacker gains no persistence, no data, and no escalation path.
Conditions required:
  • Attacker maintains authenticated session across restarts
  • No rate limiting or query restriction blocks repeated exploitation
Where this breaks in practice:
  • Alerting pipelines (Alertmanager, PagerDuty, OpsGenie) operate independently of Grafana UI availability
  • Security teams typically don't use Grafana as their primary SIEM — Splunk, Elastic, Sentinel continue operating
  • Repeated crashes will generate obvious log noise, accelerating incident detection
Detection/coverage: Repeated OOM kills and rapid restart cycles are trivially detectable by any process monitoring agent (node_exporter, Datadog, etc.).
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNone observed. Not listed in CISA KEV. No campaigns or threat actor usage reported as of 2026-09-21.
Proof-of-ConceptNo public PoC available. No exploit code on GitHub, Exploit-DB, or researcher blogs. The attack is conceptually simple (craft a large testdata query) but no weaponized tooling exists.
EPSS Score0.00376 (0.38%) — bottom quartile, indicating very low probability of exploitation in the next 30 days.
CISA KEV StatusNot listed. CISA ADP assessment marks exploitation as "none" and automatable as "no".
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H — Network-accessible, low complexity, requires low-privilege auth, availability-only impact. No scope change.
Tenable VPR3.0 (Low) — 23.72nd percentile. Tenable's risk-based scoring significantly discounts this below the CVSS base score.
Affected VersionsGrafana 8.1.0 through 11.6.13, 12.0.0–12.1.9, 12.2.0–12.2.7, 12.3.0–12.3.5, 12.4.0–12.4.1. Extremely wide range — nearly every Grafana release since August 2021.
Fixed Versions11.6.14, 12.1.10, 12.2.8, 12.3.6, 12.4.2. No distro backport data available yet for Debian/Ubuntu/RHEL packages.
Internet ExposureShodan indexes ~46,000 Grafana instances on the public internet (2025–2026 data). Most enterprise deployments are internal-only, but shadow IT and dev instances frequently leak.
Disclosure TimelinePublished 2026-03-27 by Grafana Labs. Tenable plugin 304689 released 2026-04-02. Patch available same day as advisory.
04 · The Call

Final Verdict
= UNCHANGED to MEDIUM (5.0/10)

Why this verdict

  • Authentication gate: PR:L means every attacker must first hold valid Grafana credentials. Anonymous exploitation is impossible. This immediately narrows the threat population to insiders, compromised-credential scenarios, or post-initial-access adversaries.
  • DoS-only, self-healing impact: The CVSS A:H rating describes a process crash, not a persistent outage. Grafana under systemd or Kubernetes restarts in seconds. There is zero confidentiality or integrity impact — no data exfiltration, no code execution, no lateral movement. The practical availability impact is a brief dashboard flicker, not a service-destroying event.
  • Zero exploitation interest: EPSS 0.38%, no PoC, no KEV listing, no in-the-wild sightings in nearly six months since disclosure. Attackers with valid Grafana credentials have far more valuable options (query real datasources, exfiltrate dashboard data, pivot via SSRF in data source proxies) than crashing the UI.
  • Role multiplier: Grafana occupies the *observability/visualization layer*, adjacent to but not part of the SIEM/detection plane. (a) On dev/test instances — negligible impact. (b) On typical internal monitoring — brief dashboard outage, alerting pipelines (Alertmanager, PagerDuty) continue independently. (c) On high-value observability stacks — a temporary Grafana outage does NOT disable alert evaluation or notification delivery in well-architected deployments. Blast radius is host-level (single Grafana process), not tenant/domain/fleet-scale. This does not trigger the HIGH floor because the worst-case outcome is temporary visibility loss, not domain takeover, data egress, or supply-chain compromise.
  • Wide version range increases patch surface but not urgency: Every Grafana since 8.1.0 (Aug 2021) is affected, meaning most orgs have vulnerable instances. However, the low exploitability and DoS-only impact make this a scheduled patch, not an emergency.

Why not higher?

Elevating to HIGH would require either (a) a path to code execution or data compromise, (b) evidence of active exploitation, or (c) a blast radius that reaches domain/fleet/supply-chain scale. None apply here. The vulnerability is DoS-only against a visualization layer, requires authentication, and is self-healing. The observability-plane role does not meet the HIGH floor because Grafana's crash does not disable independent alerting pipelines.

Why not lower?

Dropping to LOW would underweight the fact that the testdata datasource is enabled by default in every Grafana installation, the version range spans five years of releases, and ~46K instances are internet-exposed. An authenticated insider or compromised-credential attacker can trivially crash the service with a single API call. The 6.5 base score's A:H component is mechanically earned — the availability impact is real, just recoverable. MEDIUM at a compressed 5.0 score properly reflects the practical risk.

05 · Compensating Control

What to do — in priority order.

  1. Set memory limits on the Grafana process — Configure cgroup memory limits (systemd MemoryMax= or Kubernetes resources.limits.memory) to cap Grafana at a sane ceiling (e.g., 2–4 GB). This ensures the OOM kill is fast, contained, and doesn't starve co-located services. Deploy within the 365-day noisgate remediation window alongside the patch, or sooner if you have exposed instances.
  2. Restrict testdata datasource access via RBAC — In Grafana Enterprise, use RBAC to deny query permissions on the grafana-testdata-datasource for all roles except Admins. In OSS Grafana, remove or disable the testdata datasource instance if it's not needed — most production deployments don't use it. This eliminates the attack surface entirely.
  3. Enable query timeouts and rate limiting — Set dataproxy.timeout and query concurrency limits in grafana.ini to bound runaway queries. Pair with a reverse proxy (nginx, Envoy) that enforces per-user request rate limits on /api/ds/query. This makes sustained DoS via repeated crashes impractical.
  4. Ensure automatic restart is configured — Verify Grafana runs under a supervisor that restarts on crash — Restart=always in the systemd unit, or restartPolicy: Always in Kubernetes. This is standard but worth confirming. Recovery time should be <10 seconds.
  5. Deploy Grafana in HA mode — Run multiple Grafana replicas behind a load balancer. A single-node OOM crash doesn't take down the service. This is a best practice for production observability stacks regardless of this CVE.
What doesn't work
  • WAF rules — the malicious payload is a legitimate-looking datasource query over the standard Grafana API. No WAF signature can distinguish a "too large" testdata request from normal usage without deep application-layer understanding.
  • Network segmentation alone — while limiting Grafana to internal networks reduces the attacker pool, the threat model here is an authenticated insider or post-compromise adversary already on the internal network. Segmentation doesn't help against those actors.
  • Disabling the testdata plugin entirely via config — the testdata datasource is a core plugin, not an external one. You can prevent loading the bundled version by setting [plugin.grafana-testdata-datasource] as_external = true without providing an external binary, but this is fragile and may break in upgrades. Deleting the datasource instance via API is more reliable.
06 · Verification

Crowdsourced verification payload.

Run this script on the Grafana host (or any host that can reach the Grafana API) as any user. It queries the Grafana health and build-info endpoints — no authentication required for version detection. Usage: bash check_cve_2026_28375.sh https://grafana.internal:3000

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_28375.sh — Detect CVE-2026-28375 (Grafana testdata OOM DoS)
# Usage: bash check_cve_2026_28375.sh <GRAFANA_URL>
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

GRAFANA_URL="${1:?Usage: $0 <GRAFANA_URL>}"
GRAFANA_URL="${GRAFANA_URL%/}"

# Fetch version from build info endpoint (unauthenticated)
RESPONSE=$(curl -sf --max-time 10 "${GRAFANA_URL}/api/health" 2>/dev/null || true)

if [[ -z "$RESPONSE" ]]; then
  echo "UNKNOWN — could not reach ${GRAFANA_URL}/api/health"
  exit 2
fi

VERSION=$(echo "$RESPONSE" | grep -oP '"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' || true)

if [[ -z "$VERSION" ]]; then
  # Try /api/frontend/settings as fallback
  RESPONSE2=$(curl -sf --max-time 10 "${GRAFANA_URL}/api/frontend/settings" 2>/dev/null || true)
  VERSION=$(echo "$RESPONSE2" | grep -oP '"buildInfo".*?"version"\s*:\s*"\K[0-9]+\.[0-9]+\.[0-9]+' || true)
fi

if [[ -z "$VERSION" ]]; then
  echo "UNKNOWN — could not extract Grafana version from ${GRAFANA_URL}"
  exit 2
fi

echo "Detected Grafana version: ${VERSION}"

# Parse version components
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"

# Version comparison logic
# Vulnerable ranges:
#   8.1.0 <= v < 11.6.14
#   12.0.0 <= v < 12.1.10
#   12.2.0 <= v < 12.2.8
#   12.3.0 <= v < 12.3.6
#   12.4.0 <= v < 12.4.2

VULNERABLE=false

if (( MAJOR >= 8 && MAJOR <= 11 )); then
  if (( MAJOR == 8 && MINOR == 0 )); then
    VULNERABLE=false  # 8.0.x not affected (starts at 8.1.0)
  elif (( MAJOR == 11 && MINOR == 6 && PATCH >= 14 )); then
    VULNERABLE=false  # 11.6.14+ is patched
  elif (( MAJOR == 8 )) && (( MINOR >= 1 )); then
    VULNERABLE=true
  elif (( MAJOR >= 9 && MAJOR <= 10 )); then
    VULNERABLE=true
  elif (( MAJOR == 11 )); then
    if (( MINOR < 6 )); then
      VULNERABLE=true
    elif (( MINOR == 6 && PATCH < 14 )); then
      VULNERABLE=true
    fi
  fi
elif (( MAJOR == 12 )); then
  if (( MINOR == 0 )); then
    VULNERABLE=true  # 12.0.x has no fix in the 12.0 branch
  elif (( MINOR == 1 )); then
    if (( PATCH < 10 )); then
      VULNERABLE=true
    fi
  elif (( MINOR == 2 )); then
    if (( PATCH < 8 )); then
      VULNERABLE=true
    fi
  elif (( MINOR == 3 )); then
    if (( PATCH < 6 )); then
      VULNERABLE=true
    fi
  elif (( MINOR == 4 )); then
    if (( PATCH < 2 )); then
      VULNERABLE=true
    fi
  fi
fi

if $VULNERABLE; then
  echo "VULNERABLE — Grafana ${VERSION} is affected by CVE-2026-28375"
  echo "Upgrade to 11.6.14, 12.1.10, 12.2.8, 12.3.6, or 12.4.2+"
  exit 1
else
  echo "PATCHED — Grafana ${VERSION} is not affected by CVE-2026-28375"
  exit 0
fi
07 · Sources

Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.