VYPR
Low severity3.7OSV Advisory· Published Mar 20, 2025· Updated Apr 15, 2026

CVE-2025-29923

CVE-2025-29923

Description

go-redis is the official Redis client library for the Go programming language. Prior to 9.5.5, 9.6.3, and 9.7.3, go-redis potentially responds out of order when CLIENT SETINFO times out during connection establishment. This can happen when the client is configured to transmit its identity, there are network connectivity issues, or the client was configured with aggressive timeouts. The problem occurs for multiple use cases. For sticky connections, you receive persistent out-of-order responses for the lifetime of the connection. All commands in the pipeline receive incorrect responses. When used with the default ConnPool once a connection is returned after use with ConnPool#Put the read buffer will be checked and the connection will be marked as bad due to the unread data. This means that at most one out-of-order response before the connection is discarded. This issue is fixed in 9.5.5, 9.6.3, and 9.7.3. You can prevent the vulnerability by setting the flag DisableIndentity to true when constructing the client instance.

AI Insight

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

go-redis versions before 9.5.5, 9.6.3, and 9.7.3 may return out-of-order responses when CLIENT SETINFO times out during connection setup.

Vulnerability

Overview

CVE-2025-29923 affects the go-redis client library for Go, versions prior to 9.5.5, 9.6.3, and 9.7.3. The vulnerability occurs when the CLIENT SETINFO command, used to transmit client identity, times out during connection establishment. This can lead to out-of-order response processing on the connection [1][4].

Attack

Vector and Exploitation

Exploitation requires network conditions that cause a timeout on the SETINFO command, such as connectivity issues or aggressive client timeouts. If the connection is sticky (non-pooled), all subsequent commands receive incorrect responses from the server. With the default ConnPool, the connection is discarded after detecting unread data, limiting exposure to at most one out-of-order response [1]. No authentication or special privileges are needed; the attacker must be able to influence network timing or the client's timeout settings.

Impact

An attacker who can trigger the timeout may cause the client to misinterpret server responses, leading to data corruption or logic errors in applications relying on correct command-response ordering. The impact is limited by the fact that in pooled configurations, affected connections are quickly discarded [1][4].

Mitigation

The vulnerability is fixed in go-redis versions 9.5.5, 9.6.3, and 9.7.3. Users can also prevent the issue by setting DisableIdentity (or the deprecated DisableIndentity) to true in the client options, which disables the SETINFO command entirely [3].

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
github.com/redis/go-redis/v9Go
>= 9.7.0-beta.1, < 9.7.39.7.3
github.com/redis/go-redis/v9Go
>= 9.6.0b1, < 9.6.39.6.3
github.com/redis/go-redis/v9Go
>= 9.5.1, < 9.5.59.5.5

Affected products

1
  • Range: extra/rediscensus/v9.7.0, extra/rediscensus/v9.7.1, extra/rediscensus/v9.7.2, …

Patches

4
d236865b0cfa

fix: handle network error on SETINFO (#3295) (CVE-2025-29923)

https://github.com/redis/go-redisNedyalko DyakovMar 19, 2025via ghsa
9 files changed · +104 28
  • bench_decode_test.go+2 2 modified
    @@ -30,7 +30,7 @@ func NewClientStub(resp []byte) *ClientStub {
     		Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
     			return stub.stubConn(initHello), nil
     		},
    -		DisableIndentity: true,
    +		DisableIdentity: true,
     	})
     	return stub
     }
    @@ -46,7 +46,7 @@ func NewClusterClientStub(resp []byte) *ClientStub {
     		Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
     			return stub.stubConn(initHello), nil
     		},
    -		DisableIndentity: true,
    +		DisableIdentity: true,
     
     		ClusterSlots: func(_ context.Context) ([]ClusterSlot, error) {
     			return []ClusterSlot{
    
  • options.go+10 1 modified
    @@ -148,9 +148,18 @@ type Options struct {
     	// Enables read only queries on slave/follower nodes.
     	readOnly bool
     
    -	// Disable set-lib on connect. Default is false.
    +	// DisableIndentity - Disable set-lib on connect.
    +	//
    +	// default: false
    +	//
    +	// Deprecated: Use DisableIdentity instead.
     	DisableIndentity bool
     
    +	// DisableIdentity is used to disable CLIENT SETINFO command on connect.
    +	//
    +	// default: false
    +	DisableIdentity bool
    +
     	// Add suffix to client name. Default is empty.
     	IdentitySuffix string
     
    
  • osscluster.go+15 3 modified
    @@ -90,8 +90,19 @@ type ClusterOptions struct {
     	ConnMaxIdleTime time.Duration
     	ConnMaxLifetime time.Duration
     
    -	TLSConfig        *tls.Config
    -	DisableIndentity bool // Disable set-lib on connect. Default is false.
    +	TLSConfig *tls.Config
    +
    +	// DisableIndentity - Disable set-lib on connect.
    +	//
    +	// default: false
    +	//
    +	// Deprecated: Use DisableIdentity instead.
    +	DisableIndentity bool
    +
    +	// DisableIdentity is used to disable CLIENT SETINFO command on connect.
    +	//
    +	// default: false
    +	DisableIdentity bool
     
     	IdentitySuffix string // Add suffix to client name. Default is empty.
     
    @@ -303,7 +314,8 @@ func (opt *ClusterOptions) clientOptions() *Options {
     		MaxActiveConns:   opt.MaxActiveConns,
     		ConnMaxIdleTime:  opt.ConnMaxIdleTime,
     		ConnMaxLifetime:  opt.ConnMaxLifetime,
    -		DisableIndentity: opt.DisableIndentity,
    +		DisableIdentity:  opt.DisableIdentity,
    +		DisableIndentity: opt.DisableIdentity,
     		IdentitySuffix:   opt.IdentitySuffix,
     		TLSConfig:        opt.TLSConfig,
     		// If ClusterSlots is populated, then we probably have an artificial
    
  • README.md+5 3 modified
    @@ -178,16 +178,18 @@ By default, go-redis automatically sends the client library name and version dur
     
     #### Disabling Identity Verification
     
    -When connection identity verification is not required or needs to be explicitly disabled, a `DisableIndentity` configuration option exists. In V10 of this library, `DisableIndentity` will become `DisableIdentity` in order to fix the associated typo.
    +When connection identity verification is not required or needs to be explicitly disabled, a `DisableIdentity` configuration option exists.
    +Initially there was a typo and the option was named `DisableIndentity` instead of `DisableIdentity`. The misspelled option is marked as Deprecated and will be removed in V10 of this library.
    +Although both options will work at the moment, the correct option is `DisableIdentity`. The deprecated option will be removed in V10 of this library, so please use the correct option name to avoid any issues.
     
    -To disable verification, set the `DisableIndentity` option to `true` in the Redis client options:
    +To disable verification, set the `DisableIdentity` option to `true` in the Redis client options:
     
     ```go
     rdb := redis.NewClient(&redis.Options{
         Addr:            "localhost:6379",
         Password:        "",
         DB:              0,
    -    DisableIndentity: true, // Disable set-info on connect
    +    DisableIdentity: true, // Disable set-info on connect
     })
     ```
     
    
  • redis.go+6 2 modified
    @@ -350,7 +350,7 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
     		return err
     	}
     
    -	if !c.opt.DisableIndentity {
    +	if !c.opt.DisableIdentity && !c.opt.DisableIndentity {
     		libName := ""
     		libVer := Version()
     		if c.opt.IdentitySuffix != "" {
    @@ -359,7 +359,11 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
     		p := conn.Pipeline()
     		p.ClientSetInfo(ctx, WithLibraryName(libName))
     		p.ClientSetInfo(ctx, WithLibraryVersion(libVer))
    -		_, _ = p.Exec(ctx)
    +		// Handle network errors (e.g. timeouts) in CLIENT SETINFO to avoid
    +		// out of order responses later on.
    +		if _, err = p.Exec(ctx); err != nil && !isRedisError(err) {
    +			return err
    +		}
     	}
     
     	if c.opt.OnConnect != nil {
    
  • redis_test.go+7 0 modified
    @@ -396,6 +396,13 @@ var _ = Describe("Client timeout", func() {
     	})
     
     	testTimeout := func() {
    +		It("SETINFO timeouts", func() {
    +			conn := client.Conn()
    +			err := conn.Ping(ctx).Err()
    +			Expect(err).To(HaveOccurred())
    +			Expect(err.(net.Error).Timeout()).To(BeTrue())
    +		})
    +
     		It("Ping timeouts", func() {
     			err := client.Ping(ctx).Err()
     			Expect(err).To(HaveOccurred())
    
  • ring.go+16 4 modified
    @@ -98,9 +98,19 @@ type RingOptions struct {
     	TLSConfig *tls.Config
     	Limiter   Limiter
     
    +	// DisableIndentity - Disable set-lib on connect.
    +	//
    +	// default: false
    +	//
    +	// Deprecated: Use DisableIdentity instead.
     	DisableIndentity bool
    -	IdentitySuffix   string
    -	UnstableResp3    bool
    +
    +	// DisableIdentity is used to disable CLIENT SETINFO command on connect.
    +	//
    +	// default: false
    +	DisableIdentity bool
    +	IdentitySuffix  string
    +	UnstableResp3   bool
     }
     
     func (opt *RingOptions) init() {
    @@ -167,9 +177,11 @@ func (opt *RingOptions) clientOptions() *Options {
     		TLSConfig: opt.TLSConfig,
     		Limiter:   opt.Limiter,
     
    +		DisableIdentity:  opt.DisableIdentity,
     		DisableIndentity: opt.DisableIndentity,
    -		IdentitySuffix:   opt.IdentitySuffix,
    -		UnstableResp3:    opt.UnstableResp3,
    +
    +		IdentitySuffix: opt.IdentitySuffix,
    +		UnstableResp3:  opt.UnstableResp3,
     	}
     }
     
    
  • sentinel.go+24 7 modified
    @@ -80,9 +80,20 @@ type FailoverOptions struct {
     
     	TLSConfig *tls.Config
     
    +	// DisableIndentity - Disable set-lib on connect.
    +	//
    +	// default: false
    +	//
    +	// Deprecated: Use DisableIdentity instead.
     	DisableIndentity bool
    -	IdentitySuffix   string
    -	UnstableResp3    bool
    +
    +	// DisableIdentity is used to disable CLIENT SETINFO command on connect.
    +	//
    +	// default: false
    +	DisableIdentity bool
    +
    +	IdentitySuffix string
    +	UnstableResp3  bool
     }
     
     func (opt *FailoverOptions) clientOptions() *Options {
    @@ -118,9 +129,11 @@ func (opt *FailoverOptions) clientOptions() *Options {
     
     		TLSConfig: opt.TLSConfig,
     
    +		DisableIdentity:  opt.DisableIdentity,
     		DisableIndentity: opt.DisableIndentity,
    -		IdentitySuffix:   opt.IdentitySuffix,
    -		UnstableResp3:    opt.UnstableResp3,
    +
    +		IdentitySuffix: opt.IdentitySuffix,
    +		UnstableResp3:  opt.UnstableResp3,
     	}
     }
     
    @@ -156,9 +169,11 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options {
     
     		TLSConfig: opt.TLSConfig,
     
    +		DisableIdentity:  opt.DisableIdentity,
     		DisableIndentity: opt.DisableIndentity,
    -		IdentitySuffix:   opt.IdentitySuffix,
    -		UnstableResp3:    opt.UnstableResp3,
    +
    +		IdentitySuffix: opt.IdentitySuffix,
    +		UnstableResp3:  opt.UnstableResp3,
     	}
     }
     
    @@ -197,8 +212,10 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions {
     
     		TLSConfig: opt.TLSConfig,
     
    +		DisableIdentity:  opt.DisableIdentity,
     		DisableIndentity: opt.DisableIndentity,
    -		IdentitySuffix:   opt.IdentitySuffix,
    +
    +		IdentitySuffix: opt.IdentitySuffix,
     	}
     }
     
    
  • universal.go+19 6 modified
    @@ -61,14 +61,24 @@ type UniversalOptions struct {
     	RouteByLatency bool
     	RouteRandomly  bool
     
    -	// The sentinel master name.
    -	// Only failover clients.
    -
    +	// MasterName is the sentinel master name.
    +	// Only for failover clients.
     	MasterName string
     
    +	// DisableIndentity - Disable set-lib on connect.
    +	//
    +	// default: false
    +	//
    +	// Deprecated: Use DisableIdentity instead.
     	DisableIndentity bool
    -	IdentitySuffix   string
    -	UnstableResp3    bool
    +
    +	// DisableIdentity is used to disable CLIENT SETINFO command on connect.
    +	//
    +	// default: false
    +	DisableIdentity bool
    +
    +	IdentitySuffix string
    +	UnstableResp3  bool
     
     	// IsClusterMode can be used when only one Addrs is provided (e.g. Elasticache supports setting up cluster mode with configuration endpoint).
     	IsClusterMode bool
    @@ -116,6 +126,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions {
     
     		TLSConfig: o.TLSConfig,
     
    +		DisableIdentity:  o.DisableIdentity,
     		DisableIndentity: o.DisableIndentity,
     		IdentitySuffix:   o.IdentitySuffix,
     		UnstableResp3:    o.UnstableResp3,
    @@ -163,8 +174,9 @@ func (o *UniversalOptions) Failover() *FailoverOptions {
     
     		TLSConfig: o.TLSConfig,
     
    -		ReplicaOnly:     o.ReadOnly,
    +		ReplicaOnly: o.ReadOnly,
     
    +		DisableIdentity:  o.DisableIdentity,
     		DisableIndentity: o.DisableIndentity,
     		IdentitySuffix:   o.IdentitySuffix,
     		UnstableResp3:    o.UnstableResp3,
    @@ -209,6 +221,7 @@ func (o *UniversalOptions) Simple() *Options {
     
     		TLSConfig: o.TLSConfig,
     
    +		DisableIdentity:  o.DisableIdentity,
     		DisableIndentity: o.DisableIndentity,
     		IdentitySuffix:   o.IdentitySuffix,
     		UnstableResp3:    o.UnstableResp3,
    

Vulnerability mechanics

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

References

5

News mentions

0

No linked articles in our index yet.