Skip to content

[Cache] Redis Sentinel authentication incorrectly passed to Sentinel server in phpredis >= 5.3.2 #63261

@zgolus

Description

@zgolus

Symfony version(s) affected

7.4.4

Description

Since Symfony 7.4.4, Redis master credentials from DSN are incorrectly passed to Sentinel servers when using phpredis >= 5.3.2, breaking connections to Sentinel servers that don't have requirepass configured (a common secure setup using network isolation).

Environment

  • PHP version: 8.5
  • phpredis version: 6.3
  • Redis Sentinel: 3 nodes without requirepass (password-free, protected by firewall)
  • Redis Master: Password-protected with ACL (user: default, password: configured)

Application DSN:

redis:default:password@?host[10.0.0.21:26379]&host[10.0.0.22:26379]&host[10.0.0.23:26379]&sentinel_master=ft-redis-master&timeout=10&read_timeout=8&retry_interval=100

Expected Behavior

  • App queries Sentinel without authentication to get Redis master address
  • App connects to Redis master with authentication
  • This worked in Symfony 7.4.3

Actual Behavior (7.4.4+)

app.ERROR: Exception caught by ExceptionListener
{"message":"Failed to retrieve master information from sentinel \"ft-redis-master\"."}

Symfony 7.4.4+ passes the Redis master password to the Sentinel server connection, which rejects it because Sentinel doesn't have requirepass configured.

Possible root Cause

PR #62852 (included in 7.4.4) added line 176 to fix DSN auth not being passed to Redis clusters:

$params['auth'] ??= $auth;

This ensures DSN credentials are copied to $params['auth']. Combined with the $passAuth check:

$passAuth = null !== $params['auth'] && (!$isRedisExt || \defined('Redis::OPT_NULL_MULTIBULK_AS_NULL'));

For phpredis >= 5.3.2 (where OPT_NULL_MULTIBULK_AS_NULL is defined):

  • $passAuth evaluates to true
  • Auth is passed to Sentinel via $options['auth']:
if ($passAuth) {
    $options['auth'] = $params['auth'];
}
$sentinel = new \RedisSentinel($options);

Why it worked in 7.4.3

Before PR #62852:

  • $auth was extracted from DSN user:password@ part
  • But $params['auth'] was NOT automatically populated from $auth
  • Only auth from query parameters was used
  • Since our auth is in DSN credentials (not query params), $params['auth'] was null
  • Therefore $passAuth was false
  • Auth was NOT passed to Sentinel ✅
  • Auth was still applied to Redis master via explicit $redis->auth() call on line 303

The Problem

Redis Sentinel has two separate authentication contexts:

  1. Sentinel server auth (requirepass): Password to query Sentinel itself
  2. Redis master auth (sentinel auth-pass): Password for Redis instances Sentinel monitors

Symfony's RedisTrait doesn't distinguish between these two. The DSN password is for the Redis master, but Symfony 7.4.4+ also passes it to Sentinel server connections.

How to reproduce

  1. Set up Redis Sentinel cluster without requirepass on Sentinel servers
  2. Configure Redis master with password authentication
  3. Use Symfony 7.4.4+ with phpredis 6.3
  4. Use DSN: redis:default:password@?host[sentinel:26379]&sentinel_master=mymaster
  5. Attempt connection
  6. Observe: "Failed to retrieve master information from sentinel"

Possible Solution

Add a DSN parameter to control Sentinel authentication separately:

redis:default:password@?host[...]&sentinel_master=mymaster&sentinel_auth=false

Or automatically detect when Sentinel doesn't require auth and skip it, similar to how $passAuth already tries to handle this.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions