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:
- Sentinel server auth (
requirepass): Password to query Sentinel itself
- 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
- Set up Redis Sentinel cluster without
requirepass on Sentinel servers
- Configure Redis master with password authentication
- Use Symfony 7.4.4+ with phpredis 6.3
- Use DSN:
redis:default:password@?host[sentinel:26379]&sentinel_master=mymaster
- Attempt connection
- 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
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
requirepassconfigured (a common secure setup using network isolation).Environment
requirepass(password-free, protected by firewall)default, password: configured)Application DSN:
Expected Behavior
Actual Behavior (7.4.4+)
Symfony 7.4.4+ passes the Redis master password to the Sentinel server connection, which rejects it because Sentinel doesn't have
requirepassconfigured.Possible root Cause
PR #62852 (included in 7.4.4) added line 176 to fix DSN auth not being passed to Redis clusters:
This ensures DSN credentials are copied to
$params['auth']. Combined with the$passAuthcheck:For phpredis >= 5.3.2 (where
OPT_NULL_MULTIBULK_AS_NULLis defined):$passAuthevaluates totrue$options['auth']:Why it worked in 7.4.3
Before PR #62852:
$authwas extracted from DSNuser:password@part$params['auth']was NOT automatically populated from$auth$params['auth']wasnull$passAuthwasfalse$redis->auth()call on line 303The Problem
Redis Sentinel has two separate authentication contexts:
requirepass): Password to query Sentinel itselfsentinel auth-pass): Password for Redis instances Sentinel monitorsSymfony's
RedisTraitdoesn'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
requirepasson Sentinel serversredis:default:password@?host[sentinel:26379]&sentinel_master=mymasterPossible Solution
Add a DSN parameter to control Sentinel authentication separately:
Or automatically detect when Sentinel doesn't require auth and skip it, similar to how
$passAuthalready tries to handle this.Additional Context
No response