Inside the Metabase SQLi: Exploited in the Wild
Self-hosted Metabase instances must be patched as soon as possible. Wiz Research published a Threat Intel Center alert to customers upon Metabase’s disclosure. However, given the severity of this vulnerability and reported in-the-wild exploitation, we think it’s important to share more publicly. We also wanted to use this as an opportunity to highlight how AI can accelerate defensive security.
As of noon UTC on August 10th, we have observed public proof-of-concept exploits open-sourced.
By the numbers
Wiz observed that roughly 13% of cloud environments have self-hosted Metabase instances deployed. Of those instances, approximately 25% are fully internet accessible.
In terms of public data, we can see ~2,500 Metabase instances inventoried by Shodan.
Reverse Engineering the Vulnerability
The initial Metabase disclosure gives a few critical hints as to the underlying vulnerability:
The class of vulnerability is SQL Injection
The entrypoint is /api/session/reset_password
The vulnerability is present in versions 1.58+
Docker images are available for fixed versions
However, the details of the vulnerability were not released, and the patch was only made available via releases - it is not public in the current GitHub repository.
In such cases it is necessary for Wiz Research to reverse engineer the vulnerability, in order to ensure prompt detection and validation can be offered to customers. To do so, we are able to leverage the expertise developed from building autonomous AI systems for vulnerability research. We are withholding our full PoC to avoid enabling exploitation, while ensuring defenders have the necessary information to respond.
The process for reversing such vulnerabilities can be generically described through the following process:
Download vulnerable and patched JARs - in this case we used v0.58.22 and v0.58.24
Compare contents and develop a diff
Decompile compiled Clojure for the relevant class
Clone open source code, and correlate bytecode diff to source
Having reversed the patch, use it as a pointer to reconstruct the vulnerability
We prompted an agent with this process, which revealed the SQL Injection vulnerability, with the following (pseudocode) patch as the smoking gun:
(when-let [user-id (:user-id $)] - (t2/select-one [:model/User ...] :id user-id)) + (if (pos-int? user-id) + (t2/select-one [:model/User ...] :id user-id) + (log/warnf "Provider %s returned a non-positive-int :user-id (type %s); refusing to resolve a user." + provider (type user-id))))
Technical Details
The patch validates user-id as a positive integer before querying. However, user-id is not a documented parameter of /api/session/reset_password, which only expects a token and a password.
So, we can infer that the vulnerability entails providing an extra user-id key in the JSON body that the API doesn't strip. Following this lead, we used an agent to reconstruct the vulnerability, which ties together a few interesting language and framework behaviors:
Clojure's merge function combines two maps, with the second map's values overwriting the first's. Critically, it does not strip extra keys from the first map, but rather they simply pass through. In the vulnerable code, the incoming request is merged with the authentication result: (merge request (authenticate ...)). When authentication fails, the result contains no user-id, so an attacker-supplied user-id from the request survives the merge untouched.
JSON keywordization converts JSON keys into Clojure keywords during parsing. An attacker's payload {"user-id": {"raw": "SQL"}} becomes the Clojure map {:user-id {:raw "SQL"}}. This is standard behavior, but it enables the next step.
HoneySQL's :raw keyword is a feature that allows embedding literal SQL strings, bypassing parameterization. It's intended for cases where developers need to include SQL that can't be expressed through the query builder. When the attacker-controlled {:raw "SQL"} value reaches a HoneySQL query, it's interpreted as a directive to inject the SQL string directly.
The injection completes when the surviving user-id value is passed to t2/select-one :id user-id. Instead of receiving an integer like 123, the query receives {:raw "(...)"}, which HoneySQL compiles into unparameterized SQL achieving arbitrary blind SQL injection.
Metabase supports multiple databases: H2 by default, but PostgreSQL, MySQL, or MariaDB are recommended for production. The injection payload is database-dependent. The vulnerability has been present since version 1.58. This was when the auth_identity module was refactored, which introduced this vulnerability.
Variant Hunting
Once we identified the root cause, we also made a quick pass at identifying any unpatched variants of this issue lingering in the repository. This included generating Static Analysis rules for the relevant code patterns, running them to generate candidates, and using our agentic approach to validate or invalidate those candidates. In this case, we reviewed all merge.*request patterns, as well as all auth-identity/login! call sites.
Recommendations
If you need to investigate manually:
Review /api/session/properties to determine if a Metabase instance is running a vulnerable version
To check for exploitability, you should modify the following command with your desired SQL:
curl -X POST https://TARGET/api/session/reset_password \-H "Content-Type: application/json" \-d '{"token":"x","password":"y","user-id":{"raw":"SQL_PLACEHOLDER"}}'
Wiz customers should refer to the pre-built advisory in the Wiz Threat Intel Center for actionable steps to investigate, remediate, and harden their environments. Wiz Research will continue to update that advisory as the situation develops.
Automating DISA STIG Compliance for Amazon Linux 2023 and Windows Server 2025, giving defense and federal teams immediate and continuous hardening validation.
Announcing new capabilities that help organizations prepare for the AI era by expanding visibility and accelerating response, so security teams can defend at machine speed.
Get a personalized demo
Ready to see Wiz in action?
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management
How it works
Once you click Generate, Ollama reads this article and crafts 5 comprehension questions. Your answers are graded against the article content — general knowledge won't be enough. Score 70+ to count toward your certificate.
Questions are cached — you'll always get the same 5 for this article.