VYPR
Moderate severityNVD Advisory· Published Apr 14, 2023· Updated Feb 6, 2025

vitess allows users to create keyspaces that can deny access to already existing keyspaces

CVE-2023-29194

Description

Creating a keyspace with '/' in its name crashes VTAdmin and vtctldclient GetKeyspaces, a denial-of-service fixed in Vitess 16.0.1.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Creating a keyspace with '/' in its name crashes VTAdmin and vtctldclient GetKeyspaces, a denial-of-service fixed in Vitess 16.0.1.

Overview

Vitess, a database clustering system for horizontal scaling of MySQL, is vulnerable to a denial-of-service attack via improperly named keyspaces. [1] Both the VTAdmin web interface and the vtctldclient GetKeyspaces CLI command become inoperable when a keyspace name contains the forward slash (/) character, returning errors and preventing normal management operations on other keyspaces via these tools. [1][2]

Root

Cause and Exploitation The vulnerability stems from insufficient input validation in the TopoServer's keyspace creation and retrieval functions. [2] Prior to version 16.0.1, Vitess did not reject keyspace names containing the / character. [2] Either a malicious actor or an inadvertent user could create such a keyspace, triggering the denial-of-service condition. [1][2] Importantly, the attack requires the ability to create a keyspace, which is a privileged operation typically granted to database administrators. [1] The flaw was addressed by adding a ValidateKeyspaceName function that rejects names containing /. [2]

Impact

Once a keyspace with a / in its name exists, any attempt to view keyspaces via VTAdmin or list them with vtctldclient GetKeyspaces results in an error, effectively blocking graphical and CLI-based administration of all keyspaces. [1] However, individual keyspaces can still be managed using the vtctldclient directly, and the offending keyspace can be deleted via CLI to restore full functionality. [1] The vulnerability is a denial-of-service (DoS) issue, not data corruption or disclosure. [1]

Mitigation and

Status The fix is included in Vitess release 16.0.1. [1][2][3] Users running versions prior to 16.0.1 should upgrade immediately. As a workaround, administrators can delete the malformed keyspace using the CLI (vtctldclient) to clear the error. [1]

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
vitess.io/vitessGo
< 0.16.10.16.1

Affected products

2

Patches

1
adf10196760a

[Backport] Update topo {Get,Create}Keyspace to prevent invalid keyspace names (#12732) (#12771)

https://github.com/vitessio/vitessAndrew MasonMar 30, 2023via ghsa
4 files changed · +105 0
  • changelog/16.0/16.0.1/summary.md+6 0 modified
    @@ -7,3 +7,9 @@ Below is a summary of this Go patch release. You can learn more [here](https://g
     
     > go1.20.2 (released 2023-03-07) includes a security fix to the crypto/elliptic package, as well as bug fixes to the compiler, the covdata command, the linker, the runtime, and the crypto/ecdh, crypto/rsa, crypto/x509, os, and syscall packages.
     
    +### Keyspace name validation in TopoServer
    +
    +Prior to v16.0.1, it was possible to create a keyspace with invalid characters, which would then be inaccessible to various cluster management operations.
    +
    + Keyspace names may no longer contain the forward slash ("/") character, and TopoServer's `GetKeyspace` and `CreateKeyspace` methods return an error if given such a name.
    +
    
  • go/vt/topo/keyspace.go+23 0 modified
    @@ -18,6 +18,7 @@ package topo
     
     import (
     	"path"
    +	"strings"
     
     	"google.golang.org/protobuf/proto"
     
    @@ -54,6 +55,20 @@ func (ki *KeyspaceInfo) SetKeyspaceName(name string) {
     	ki.keyspace = name
     }
     
    +var invalidKeyspaceNameChars = "/"
    +
    +// ValidateKeyspaceName checks if the provided name is a valid name for a
    +// keyspace.
    +//
    +// As of v16.0.1, "all invalid characters" is just the forward slash ("/").
    +func ValidateKeyspaceName(name string) error {
    +	if strings.ContainsAny(name, invalidKeyspaceNameChars) {
    +		return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "keyspace name %s contains invalid characters; may not contain any of the following: %+v", name, strings.Split(invalidKeyspaceNameChars, ""))
    +	}
    +
    +	return nil
    +}
    +
     // GetServedFrom returns a Keyspace_ServedFrom record if it exists.
     func (ki *KeyspaceInfo) GetServedFrom(tabletType topodatapb.TabletType) *topodatapb.Keyspace_ServedFrom {
     	for _, ksf := range ki.ServedFroms {
    @@ -161,6 +176,10 @@ func (ki *KeyspaceInfo) ComputeCellServedFrom(cell string) []*topodatapb.SrvKeys
     // CreateKeyspace wraps the underlying Conn.Create
     // and dispatches the event.
     func (ts *Server) CreateKeyspace(ctx context.Context, keyspace string, value *topodatapb.Keyspace) error {
    +	if err := ValidateKeyspaceName(keyspace); err != nil {
    +		return vterrors.Wrapf(err, "CreateKeyspace: %s", err)
    +	}
    +
     	data, err := proto.Marshal(value)
     	if err != nil {
     		return err
    @@ -181,6 +200,10 @@ func (ts *Server) CreateKeyspace(ctx context.Context, keyspace string, value *to
     
     // GetKeyspace reads the given keyspace and returns it
     func (ts *Server) GetKeyspace(ctx context.Context, keyspace string) (*KeyspaceInfo, error) {
    +	if err := ValidateKeyspaceName(keyspace); err != nil {
    +		return nil, vterrors.Wrapf(err, "GetKeyspace: %s", err)
    +	}
    +
     	keyspacePath := path.Join(KeyspacesPath, keyspace, KeyspaceFile)
     	data, version, err := ts.globalCell.Get(ctx, keyspacePath)
     	if err != nil {
    
  • go/vt/topo/topotests/keyspace_test.go+72 0 added
    @@ -0,0 +1,72 @@
    +/*
    +Copyright 2023 The Vitess Authors.
    +
    +Licensed under the Apache License, Version 2.0 (the "License");
    +you may not use this file except in compliance with the License.
    +You may obtain a copy of the License at
    +
    +    http://www.apache.org/licenses/LICENSE-2.0
    +
    +Unless required by applicable law or agreed to in writing, software
    +distributed under the License is distributed on an "AS IS" BASIS,
    +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +See the License for the specific language governing permissions and
    +limitations under the License.
    +*/
    +
    +package topotests
    +
    +import (
    +	"context"
    +	"testing"
    +
    +	"github.com/stretchr/testify/assert"
    +	"github.com/stretchr/testify/require"
    +
    +	"vitess.io/vitess/go/vt/topo/memorytopo"
    +	"vitess.io/vitess/go/vt/vterrors"
    +
    +	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    +	"vitess.io/vitess/go/vt/proto/vtrpc"
    +)
    +
    +func TestCreateKeyspace(t *testing.T) {
    +	ts := memorytopo.NewServer("zone1")
    +	ctx := context.Background()
    +
    +	t.Run("valid name", func(t *testing.T) {
    +		err := ts.CreateKeyspace(ctx, "ks", &topodatapb.Keyspace{})
    +		require.NoError(t, err)
    +	})
    +	t.Run("invalid name", func(t *testing.T) {
    +		err := ts.CreateKeyspace(ctx, "no/slashes/allowed", &topodatapb.Keyspace{})
    +		assert.Error(t, err)
    +		assert.Equal(t, vtrpc.Code_INVALID_ARGUMENT, vterrors.Code(err), "%+v", err)
    +	})
    +}
    +
    +func TestGetKeyspace(t *testing.T) {
    +	ts := memorytopo.NewServer("zone1")
    +	ctx := context.Background()
    +
    +	t.Run("valid name", func(t *testing.T) {
    +		// First, create the keyspace.
    +		err := ts.CreateKeyspace(ctx, "ks", &topodatapb.Keyspace{})
    +		require.NoError(t, err)
    +
    +		// Now, get it.
    +		ks, err := ts.GetKeyspace(ctx, "ks")
    +		require.NoError(t, err)
    +		assert.NotNil(t, ks)
    +	})
    +
    +	t.Run("invalid name", func(t *testing.T) {
    +		// We can't create the keyspace (because we can't create a keyspace
    +		// with an invalid name), so we'll validate the error we get is *not*
    +		// NOT_FOUND.
    +		ks, err := ts.GetKeyspace(ctx, "no/slashes/allowed")
    +		assert.Error(t, err)
    +		assert.Equal(t, vtrpc.Code_INVALID_ARGUMENT, vterrors.Code(err), "%+v", err)
    +		assert.Nil(t, ks)
    +	})
    +}
    
  • go/vt/vtorc/inst/keyspace_dao.go+4 0 modified
    @@ -30,6 +30,10 @@ var ErrKeyspaceNotFound = errors.New("keyspace not found")
     
     // ReadKeyspace reads the vitess keyspace record.
     func ReadKeyspace(keyspaceName string) (*topo.KeyspaceInfo, error) {
    +	if err := topo.ValidateKeyspaceName(keyspaceName); err != nil {
    +		return nil, err
    +	}
    +
     	query := `
     		select
     			keyspace_type,
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.