August 8, 2026
The Metabase Breach Wasn’t Just a SQL Injection Problem
SQL injection explains how the attacker got in. It doesn’t explain why getting into one analytics tool exposed an entire data estate.
By Vishwamdhavale
4 min read
SQL injection explains how the attacker got in. It doesn't explain why getting into one analytics tool exposed an entire data estate.
On August 6, 2026, Metabase disclosed a vulnerability with a CVSS score of 10.0 an unauthenticated SQL injection that could give an attacker administrator access to the instance. Metabase says it discovered the attack on its own Cloud platform on August 3, patched it, then disclosed publicly three days later. Customers running self-hosted instances found out about the vulnerability and the fix at the same time. Two of them, Framework and Tally, later told their own users that data had been exposed.
SQL injection isn't the interesting part here. It's a known bug class, decades old, and Metabase closed it within days. What's interesting is what the attacker could reach once they were past the front door.
Metabase wasn't just a web app with a bug in it. It was a gateway that had been configured to reach every other database an admin had connected and it needed working access to all of them to do its job.
What the breach actually exposed
Metabase hasn't published a customer list these are companies that came forward on their own, which means the two below are the floor, not the full count.
Framework, the repairable-laptop maker, notified its entire customer base on August 6. Names, emails, phone numbers, physical addresses, and login IPs were exposed; payment data wasn't. Framework says the breach reached "all customers," without giving a number. Afterward, they rotated credentials across every database connected to their Metabase instance and started reviewing how much customer data they expose to BI tooling at all which is the correct response, and exactly the kind of thing this piece is arguing for.
Tally, the online form builder, disclosed on the same timeline: attacker got customer email addresses and password hashes, but not the forms or submitted responses, because those live in a separate system. Tally cut off Metabase's access to its database entirely and reported the incident to Belgium's data protection authority.
The difference between the two is the point. Tally's forms lived outside Metabase's reach entirely, so that data was never exposed the blast radius stopped exactly where Metabase's own access stopped. Framework's customer records were reachable through the connection, so they went out. Both companies were notified by Metabase that their environments had been compromised. That matters because the compromise crossed a trust boundary neither company's own application controlled.
Why one bug had this much reach
Metabase's pitch is that it can query your Postgres, your Snowflake, your MySQL, without your analysts touching the database directly. To pull that off, it has to hold the connection details for everything it's been pointed at host, credentials, all of it inside its own application database, separate from any of the databases it connects to.
Those details are encrypted at rest. That's useful, but it doesn't solve the underlying problem: which is that Metabase itself has to decrypt that material to connect anywhere. Encryption at rest stops someone who steals a database backup. It does much less once an attacker has enough control over the running application to just ask it to decrypt and connect, which is what admin access via this injection path could ultimately hand them.
So the injection was the first step. What it opened up was everything downstream of it the application's own ability to unlock and use every connection it held.
SQL injection → application compromise → decrypt stored connection material
→ connect as Metabase to whatever it was configured to reachSQL injection → application compromise → decrypt stored connection material
→ connect as Metabase to whatever it was configured to reachThe bug lived at the first arrow. Everything that made this expensive lived after it.
Storing credentials isn't the whole problem
It's tempting to stop at "storing credentials is risky." True, but it's not the sharp part of this.
Even with correct encryption, correct rotation, credentials pulled from a real secrets manager the application still holds the ability to use all of it, on demand, whenever it's running. Compromise the app with enough privilege and you inherit whatever it was trusted to reach. Not because a password leaked in plaintext somewhere, but because holding working access to a dozen systems at once was the entire job description.
The better question isn't "is the storage secure?" It's: what happens to everything this tool can reach when the tool itself is compromised?
What patching doesn't fix
Upgrading closes the injection. It doesn't tell you whether the credentials sitting in the app database during the exposure window got used, and it doesn't touch the structural fact that any tool built to reach a lot of systems at once carries this risk by design whatever its specific storage mechanism looks like.
If you're on self-hosted Metabase, get to the minimum safe release for your branch: 0.58.24, 0.59.21, 0.60.17, 0.61.11, 0.62.9, or 0.63.5. After that, there's a rough order to the response.
First, containment. Check your logs for the attack signature a POST /api/session/reset_password returning 400, immediately followed by a GET /api/user/current returning 200. If it's there, that's confirmed, not "possible." Kill every session by truncating core_session. Pull any API keys or admin accounts you don't recognize.
Then recovery. Rotate credentials for every connected database not just the ones you suspect were touched, because you can't scope that from inside a system that just had admin access handed to a stranger. Framework did exactly this: rotated credentials across every database tied to its Metabase instance, and is now reconsidering how much data it hands BI tools at all. Worth pulling query history and warehouse logs for anything odd during the exposure window while you're at it.
Finally, fix the architecture: least-privilege roles instead of full production access, read replicas or scoped schemas instead of pointing BI tools straight at prod, short-lived credentials where the connected system supports them. None of that removes the trust relationship Metabase still needs some access to function but it changes what that access is worth if the application itself gets popped.
Past Metabase
None of this is specific to Metabase. Think about anything whose job is holding credentials for a bunch of other systems an ETL pipeline, a CI/CD runner, an observability agent, an internal admin panel. Compromise that thing and you don't just get the thing. You get whatever it was trusted to reach.
Patch the bug. Do it now if you're on an affected branch. But the real boundary was never Metabase itself. It was everything Metabase had been trusted to touch.
If you're running self-hosted Metabase on the 0.58–0.63 branch range, check your logs for the pattern above before anything else.