Percent-encoded colon in URI username shifts the user/password split
Problem
JedisURIHelper.getUser and getPassword read uri.getUserInfo() and then split(":", 2). URI.getUserInfo() returns the decoded form, so a percent-encoded colon (%3A) in the username has already become a literal : by the time the split runs, and the split lands on it instead of on the real separator.
For redis://us%3Aer:pw@host:6379/0 the result is user us with password er:pw, where the URI means user us:er with password pw. The client then sends AUTH us er:pw, so the wrong ACL identity is presented and the connection is refused with an error that points at the wrong user.
ACL usernames aren't restricted to URI-safe characters, and namespaced names such as svc:billing are a natural fit for them. The only way to put one in a URI is to percent-encode the colon, which is exactly the input that breaks. The same happens for any URI assembled with URLEncoder or a URI builder, since those encode : in the username as a matter of course.
One constraint on any fix: userinfo is not form data, so a literal + in a password must stay a +. Decoding the split halves has to guard against URLDecoder's plus-to-space rule.
Minimal reproducible example
No server needed:
URI uri = new URI("redis://us%3Aer:pw@host:9000/0");
JedisURIHelper.getUser(uri); // "us" (expected "us:er")
JedisURIHelper.getPassword(uri); // "er:pw" (expected "pw")As a unit test in JedisURIHelperTest:
@Test
public void shouldKeepEncodedColonInsideUsername() throws URISyntaxException {
URI uri = new URI("redis://us%3Aer:pw@host:9000/0");
assertEquals("us:er", JedisURIHelper.getUser(uri));
assertEquals("pw", JedisURIHelper.getPassword(uri));
}On master this fails with expected: <us:er> but was: <us>.
Fix
Split uri.getRawUserInfo() instead, where an encoded colon is still %3A and only the real separator is a literal :, then percent-decode each half. Encoded @ or : in the password and a literal + behave as before. #4617 does this.
Source: redis/jedis