Someone left the vault combination taped to the front door, and five banks have already been robbed
CVE-2026-72898 is an unauthenticated SQL injection in Metabase's POST /api/session/reset_password endpoint. The root cause is a failure to strip undeclared fields from the password-reset JSON body: an attacker sends a crafted user-id key containing a HoneySQL :raw directive, which Metabase's Clojure query-building stack interprets as literal SQL rather than a parameterized value. This grants blind SQL injection against the application database (H2, PostgreSQL, or MySQL depending on deployment), enabling the attacker to overwrite user records and promote themselves to Metabase administrator. From admin, the attacker reads every stored database connection string — including credentials for Snowflake, BigQuery, Redshift, Oracle, MongoDB, and PostgreSQL warehouses. Affected versions span 0.58 / 1.58 through 0.63.4 / 1.63.4. Fixed releases: 0.58.24, 0.59.21, 0.60.17, 0.61.11, 0.62.9, 0.63.5 (and corresponding 1.x Enterprise builds).
The vendor score of CVSS 10.0 CRITICAL is fully warranted and, if anything, undersells the blast radius. This is not a theoretical risk: five companies — Framework, Tally, n8n, Kilo Code (Anaconda), and ChecklyHQ — suffered confirmed breaches *before* the CVE was even published. CISA added it to the KEV catalog on August 11, 2026. Public proof-of-concept code has been available since August 10. The attack requires zero authentication, zero user interaction, and trivial complexity. Every self-hosted Metabase instance reachable from the internet is a live target right now.
5 steps from start to impact.
Discover Internet-Facing Metabase
/api/session/properties endpoint returns the exact version number without authentication.- Target runs self-hosted Metabase 0.58–0.63.4 or 1.58–1.63.4
- Instance is reachable over HTTP/HTTPS
- Metabase Cloud (hosted SaaS) instances are not affected — only self-hosted
- Some orgs place Metabase behind VPN or SSO gateway, removing internet exposure
user-id in POST body to /api/session/reset_password can flag attempts.Send Crafted Password-Reset Request
POST /api/session/reset_password with an extra user-id field containing a HoneySQL :raw directive: {"token":"x","password":"y","user-id":{"raw":"(SELECT ...)"}}. Clojure's merge function combines the attacker-supplied map with the authentication result without stripping unknown keys. Since the token is invalid, the auth layer returns an error — but the injected user-id key survives untouched in the merged map.- Network access to
/api/session/reset_password
- None — endpoint is unauthenticated by design
/api/session/reset_password with unexpected JSON keys.Blind SQL Injection Achieves Admin Takeover
:raw value passes into t2/select-one :id user-id, where HoneySQL emits it as literal SQL instead of a parameterized integer. The attacker uses blind boolean or time-based injection to enumerate the application database, then overwrites an admin user's password hash or creates a new admin account. Payload varies by backend: H2, PostgreSQL, or MySQL syntax required.- Knowledge of which application database backend is in use (detectable via error-based fingerprinting)
- H2 (the default embedded DB) has limited SQL surface compared to PostgreSQL, but UPDATE is sufficient
- Some WAFs may block obvious SQL keywords in JSON values
core_user table. Metabase audit log showing unexpected admin account creation or password changes.Harvest All Connected Database Credentials
GET /api/database). The attacker now has direct access to production data warehouses.- Metabase admin session obtained in Step 3
- If database credentials use IAM/OAuth rather than static passwords, stolen creds may be short-lived or role-scoped
- Network segmentation may prevent direct attacker access to internal databases from the Metabase host
GET /api/database calls retrieving connection details. Anomalous admin session from unexpected IP.Exfiltrate Data from Connected Warehouses
- Valid credentials for downstream databases
- Network path from attacker to downstream databases (direct or via Metabase host as pivot)
- Network segmentation and firewall rules may block direct attacker-to-database connections
- Database-level audit and DLP may detect bulk exfiltration
The supporting signals.
| In-the-Wild Exploitation | Confirmed active. Five companies breached as zero-day before patch: Framework, Tally (Aug 7), n8n (Aug 8), Kilo Code/Anaconda (Aug 9), ChecklyHQ (Aug 10). CISA KEV added Aug 11, 2026. |
|---|---|
| Proof-of-Concept | Public since Aug 10. Wiz published a test curl command. Multiple PoC scripts circulating. Exploitation is trivial — single HTTP request with crafted JSON body. |
| EPSS Score | 0.01074 — low percentile but lagging indicator; KEV listing and confirmed breaches override EPSS signal here. |
| KEV Status | Listed — added 2026-08-11 by CISA. Federal agencies must remediate per BOD 22-01 deadlines. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — perfect 10.0. Network-accessible, no auth, no interaction, scope change reflects downstream database compromise. |
| Affected Versions | Metabase OSS 0.58.0–0.63.4, Enterprise 1.58.0–1.63.4. Introduced during auth_identity module refactoring in the 0.58 release cycle. |
| Fixed Versions | OSS: 0.58.24, 0.59.21, 0.60.17, 0.61.11, 0.62.9, 0.63.5. Enterprise: corresponding 1.x builds. Metabase Cloud was patched server-side. |
| Exposure Data | ~2,500 instances visible on Shodan. Wiz: ~13% of cloud environments run self-hosted Metabase; ~25% of those are internet-accessible. runZero provides asset discovery queries. |
| Disclosure Timeline | Exploited in wild from at least Aug 6. Vendor advisory Aug 6. CVE published Aug 10. KEV listed Aug 11. Two-day window of exploitation before public advisory. |
| Researcher / Discoverer | Discovered via incident response to Framework breach. Bishop Fox and Wiz published independent technical analyses. Resecurity published threat intelligence on exploitation campaigns. |
noisgate verdict.
The single most decisive factor is active zero-day exploitation with confirmed breaches — five companies lost customer data before the patch existed, public PoC is trivial (one curl command), and CISA KEV-listed it within 48 hours. The blast radius is not limited to the Metabase instance: every connected data warehouse's credentials are exposed, making this a supply-chain-scale data breach vector.
Why this verdict
- Unauthenticated remote access with zero friction: The vulnerable endpoint requires no credentials, no user interaction, and trivial complexity. Every prerequisite check returns 'no barrier.' This alone sustains the CVSS 10.0 baseline.
- Active exploitation with confirmed breaches: Five named companies breached as zero-day. CISA KEV listed Aug 11. Public PoC available since Aug 10. This is not theoretical — it is happening now at scale.
- Role multiplier: Metabase is canonically a data-tier gateway — its entire purpose is to hold credentials for production databases and warehouses. In >90% of deployments, compromising Metabase admin yields credentials to Snowflake, BigQuery, Redshift, PostgreSQL, or MongoDB containing regulated/production data. The blast radius is fleet-scale data egress across every connected warehouse. This is analogous to compromising a PAM vault or secret manager. The verdict floor is CRITICAL because the affected component is inherently a high-value credential store.
- Scope change confirmed: The CVSS vector correctly marks S:C (Changed scope). The attacker pivots from the Metabase application database to every downstream data warehouse, crossing trust boundaries.
- Minimal friction across the chain: Internet exposure is meaningful (~2,500 Shodan, ~25% of cloud deployments). No step in the attack path requires insider access, social engineering, or chained vulnerabilities. A single HTTP request achieves admin takeover.
Why not higher?
This is already rated at the maximum severity (CVSS 10.0 CRITICAL). There is no higher bucket available. The rating is fully justified by unauthenticated remote exploitation, active zero-day breaches, and credential-store blast radius.
Why not lower?
Downgrading would require evidence that the attack path has meaningful friction or limited blast radius — neither is true. The endpoint is unauthenticated, the PoC is a single curl command, exploitation is confirmed in the wild with named victims, and the blast radius extends to every connected production database. The only friction point (VPN/SSO gating) applies to a minority of deployments and does not overcome the KEV listing and confirmed breaches. Treating this as anything below CRITICAL would be negligent given active exploitation.
What to do — in priority order.
- Block access to /api/session/reset_password immediately — Deploy a WAF rule or reverse-proxy configuration (nginx, HAProxy, Cloudflare) that returns 403 for any POST to
/api/session/reset_password. This disables password resets but eliminates the attack surface. Deploy within the noisgate mitigation SLA of 3 days — but given active exploitation, do this within hours. - Place Metabase behind VPN or zero-trust gateway — If not already segmented, move the Metabase instance behind a VPN, Cloudflare Access, Tailscale, or equivalent zero-trust proxy so that only authenticated internal users can reach it. This eliminates the unauthenticated attack vector from the internet.
- Rotate all stored database credentials — After patching, assume credential compromise and rotate every database connection string stored in Metabase. Prioritize production warehouses (Snowflake, BigQuery, Redshift, PostgreSQL). Check database audit logs for unauthorized access from the Metabase host IP.
- Audit Metabase admin accounts and sessions — Review
core_usertable and Metabase audit logs for unauthorized admin accounts, password changes, or sessions from unexpected IPs. Any anomaly should trigger full incident response. - Patch to fixed version — Upgrade to the fixed release for your branch (0.63.5, 0.62.9, 0.61.11, 0.60.17, 0.59.21, or 0.58.24). This is the definitive remediation. Given KEV listing, target completion within the noisgate remediation SLA of 90 days — but realistically, patch within days.
- Network-layer rate limiting does not help — the exploit requires only a single HTTP request to achieve admin takeover, so rate limiting will not prevent exploitation.
- Metabase's built-in authentication (LDAP/SAML/SSO) does not help — the vulnerable endpoint is pre-authentication by design; SSO configuration does not gate
/api/session/reset_password. - Database firewalls on downstream warehouses limit post-exploitation lateral movement but do not prevent the initial Metabase admin takeover or credential theft via the API.
Crowdsourced verification payload.
Run this script on any host with curl and network access to the target Metabase instance. No authentication required. Usage: bash check_cve_2026_72898.sh https://metabase.example.com
#!/usr/bin/env bash
# CVE-2026-72898 Metabase Version Checker
# Usage: bash check_cve_2026_72898.sh <METABASE_URL>
# Requires: curl, grep
# Privileges: none (unauthenticated endpoint)
set -euo pipefail
if [ -z "${1:-}" ]; then
echo "Usage: $0 <METABASE_BASE_URL>"
echo "Example: $0 https://metabase.example.com"
exit 3
fi
BASE_URL="${1%/}"
ENDPOINT="$BASE_URL/api/session/properties"
echo "[*] Checking Metabase version at $ENDPOINT"
RESPONSE=$(curl -sk --max-time 10 "$ENDPOINT" 2>/dev/null) || {
echo "UNKNOWN - Could not connect to $ENDPOINT"
exit 2
}
VERSION=$(echo "$RESPONSE" | grep -oP '"version"\s*:\s*\{[^}]*"tag"\s*:\s*"v([0-9]+\.[0-9]+\.?[0-9]*)"' | grep -oP '[0-9]+\.[0-9]+\.?[0-9]*' | head -1)
if [ -z "$VERSION" ]; then
echo "UNKNOWN - Could not parse version from response"
exit 2
fi
echo "[*] Detected Metabase version: $VERSION"
# Extract major.minor.patch
MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3)
PATCH=${PATCH:-0}
# Normalize: 0.xx and 1.xx map to same branch (1.xx = Enterprise)
# Strip leading 0 or 1 for branch comparison
if [ "$MAJOR" -le 1 ]; then
BRANCH=$MINOR
else
BRANCH=$MAJOR
fi
# Fixed versions by branch (minor version)
declare -A FIXED_PATCH
FIXED_PATCH[58]=24
FIXED_PATCH[59]=21
FIXED_PATCH[60]=17
FIXED_PATCH[61]=11
FIXED_PATCH[62]=9
FIXED_PATCH[63]=5
if [ "$BRANCH" -lt 58 ]; then
echo "PATCHED - Version $VERSION is below the affected range (0.58+)"
exit 0
fi
if [ "$BRANCH" -gt 63 ]; then
echo "PATCHED - Version $VERSION is above the affected range"
exit 0
fi
REQUIRED=${FIXED_PATCH[$BRANCH]:-}
if [ -z "$REQUIRED" ]; then
echo "UNKNOWN - Unrecognized branch $BRANCH"
exit 2
fi
if [ "$PATCH" -ge "$REQUIRED" ]; then
echo "PATCHED - Version $VERSION is at or above the fix ($MAJOR.$BRANCH.$REQUIRED)"
exit 0
else
echo "VULNERABLE - Version $VERSION is below the fix ($MAJOR.$BRANCH.$REQUIRED) — CVE-2026-72898 applies"
exit 1
fiIf you remember one thing.
/api/session/reset_password endpoint or pull Metabase behind a VPN *today*. Under the noisgate remediation SLA, apply the vendor patch within 90 days — but realistically, patch within the week. After patching, rotate every database credential stored in Metabase (Snowflake, BigQuery, Redshift, PostgreSQL, etc.) and audit your Metabase admin accounts and database audit logs for signs of compromise. If you find evidence of unauthorized admin sessions or credential access, escalate to full incident response immediately.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.