Vitess: Missing authorization on vttablet /debug/vrlog exposes live VReplication SQL data
Medium5.3CVE-2026-65959 · Published Aug 18, 2026 · updated Sep 15, 2026
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| vitess.io/vitess Go | >= 0.24.0-rc1, <= 0.24.2 | No fix yet |
| <= 0.23.6 | No fix yet |
Details and references
## Vulnerability Details **File**: `go/vt/vttablet/tabletmanager/vreplication/vrlog.go` ### Summary `vttablet`'s `/debug/vrlog` HTTP endpoint streams live VReplication event data , including the literal SQL DML statements being replicated by MoveTables, Reshard, Materialize, and "vitess"-strategy Online DDL workflows , with no authorization check at all. Every comparable "debugging" HTTP endpoint in vttablet/vtgate (querylogz, queryz, txlogz, livequeryz, schemaz, debugenv, hotrows, tablet_plans, query_stats, query_rules) calls `acl.CheckAccessHTTP(r, acl.DEBUGGING)` before serving data, so that the cluster operator's configured `--security-policy` (e.g. `deny-all`, `read-only`, or a custom plugin) is actually honored. `vrlog.go` is the one exception: it has zero references to the `acl` package. ### Root Cause `addHttpEndpoint()` registers `/debug/vrlog` via `servenv.HTTPHandleFunc`, and `vrlogStatsHandler()` immediately starts streaming subscribed `VrLogStats` events to the response writer without first calling `acl.CheckAccessHTTP(r, acl.DEBUGGING)`, unlike every sibling handler in the same family (see e.g. `go/vt/vttablet/tabletserver/querylogz.go`'s `querylogzHandler`, which calls the check first). The data streamed is sensitive: `go/vt/vttablet/tabletmanager/vreplication/vplayer.go` calls `NewVrLogStats(...).Send(sql)` / `.Send(event.Statement)` for every row change and statement event flowing through a VReplication stream (vplayer.go:339, 700, 771, 785) , i.e. the literal SQL (including bound data values) being copied/replicated by MoveTables, Reshard, Materialize, and Online DDL. ### Attack Scenario 1. A cluster operator configures `--security-policy=deny-all` (or `read-only`, or a custom policy) specifically to lock down debugging/admin HTTP endpoints on vttablet, relying on this being uniformly enforced. 2. An attacker who can reach the vttablet debug HTTP port (common in Kubernetes/Prometheus-scraping deployments where this port is exposed beyond localhost) , but who does NOT have the `DEBUGGING`/admin role the policy requires , sends `GET /debug/vrlog`. 3. Every other debug endpoint correctly returns `403 Forbidden`. `/debug/vrlog` returns `200 OK` and streams live VReplication event data, including raw SQL DML statements containing application data values, for as long as the attacker keeps the connection open (bounded by `timeout`/`limit` query params, repeatable). ### Impact Confidentiality impact: disclosure of live replicated application data (potentially including PII or other sensitive column values) to an unauthorized actor, bypassing an access control the operator explicitly configured. No write/modify capability; this is a read-only information-disclosure / access-control-bypass issue, scoped to the vttablet debug HTTP listener. ### Vulnerable Code ```go // go/vt/vttablet/tabletmanager/vreplication/vrlog.go func addHttpEndpoint() { servenv.HTTPHandleFunc("/debug/vrlog", func(w http.ResponseWriter, r *http.Request) { ch := vrLogStatsLogger.Subscribe("vrlogstats") defer vrLogStatsLogger.Unsubscribe(ch) vrlogStatsHandler(ch, w, r) }) } func vrlogStatsHandler(ch chan *VrLogStats, w http.ResponseWriter, r *http.Request) { timeout, limit := parseTimeoutLimitParams(r) // no acl.CheckAccessHTTP(r, acl.DEBUGGING) call anywhere in this file ... ``` ### Recommended Fix ```go import "vitess.io/vitess/go/acl" func vrlogStatsHandler(ch chan *VrLogStats, w http.ResponseWriter, r *http.Request) { if err := acl.CheckAccessHTTP(r, acl.DEBUGGING); err != nil { acl.SendError(w, err) return } timeout, limit := parseTimeoutLimitParams(r) ... ``` This mirrors the exact pattern already used by `querylogz.go`, `queryz.go`, `txlogz.go`, `livequeryz.go`, `schemaz.go`, `debugenv.go`, and `tx_serializer.go` (hotrows) in the same codebase. ### Verification Built v24.0.1 from source and wrote a standalone Go test that: (1) activates the real `deny-all` security policy via `acl.RegisterFlags`, (2) registe
- CVSS 3.1
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Severity from
- GitHub (reviewed advisory)
- Weakness
- CWE-862
- Also known as
- CVE-2026-65959, GO-2026-6356
- github.com/vitessio/vitess/security/advisories/GHSA-mhc4-g3wh-cw7m
- nvd.nist.gov/vuln/detail/CVE-2026-65959
- github.com/vitessio/vitess/pull/20467
- github.com/vitessio/vitess/commit/4c58cd70edc6b03d61cb65842c342ac08341e64f
- github.com/vitessio/vitess/commit/657662e78bde1c82df680e9cc43a686d619f8094
- github.com/vitessio/vitess/commit/d929225a450027406687d27af8dca45620945ceb
- github.com/vitessio/vitess
More vitess advisories
All| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Feb 27 | Vitess users with backup storage access can write to arbitrary file paths on restore CVE-2026-27969Criticalfixed in 0.22.4, 0.23.3 | Critical | 0.22.4, 0.23.3 |
| Feb 26 | Vitess users with backup storage access can gain unauthorized access to production deployment environments CVE-2026-27965Highno fix yet | High | No fix yet |
| Dec 32024 | Vitess allows HTML injection in /debug/querylogz & /debug/env CVE-2024-53257Medium4.9fixed in 0.19.8, 0.20.4, 0.21.1 | Medium4.9 | 0.19.8, 0.20.4, 0.21.1 |
| May 82024 | Vitess vulnerable to infinite memory consumption and vtgate crash CVE-2024-32886Medium4.9fixed in 0.17.7, 0.18.5, 0.19.4, 17.0.7 | Medium4.9 | 0.17.7, 0.18.5, 0.19.4, 17.0.7 |
| May 112023 | VTAdmin users that can create shards can deny access to other functions CVE-2023-29195Medium4.1fixed in 0.16.2 | Medium4.1 | 0.16.2 |
| Apr 112023 | vitess allows users to create keyspaces that can deny access to already existing keyspaces CVE-2023-29194Medium4.1fixed in 0.16.1 | Medium4.1 | 0.16.1 |