fix: keep credentials and 5000-digit paths out of the Redis URL errors

_redis_urls raises before any check runs and cli.main prints what it raises, so
every one of its five messages interpolated the URL it was given — password and
all — straight to stderr. They render it through _endpoint now.

_endpoint itself then echoed the whole path, so an over-long database number
came back at full length: 5132 characters of error for one bad setting. It caps
the path it renders, which protects every caller, since that string is written
into terminals, CI logs and error messages rather than reused as a URL.
This commit is contained in:
Alex committed 2026-09-17 13:34:59 +01:00
1 parent 6f981a5598
commit 8b064c96f2
2 files changed
+34 -6

No files matched your search

+22
View File
@@ -472,6 +472,28 @@ class TestRedisSelection:
assert chosen == {"broker": "redis://localhost:6379/0"}
class TestRedisUrlErrors:
"""The validator raises before any check runs, and cli.main prints what it raises."""
SECRET = "sUpErSeCrEt"
@pytest.mark.parametrize("url", [
"redis://user:sUpErSeCrEt@host:not-a-port/0",
"redis://user:sUpErSeCrEt@host:0/0",
"redis://user:sUpErSeCrEt@host:6379/queue",
"postgres://user:sUpErSeCrEt@host:6379/0",
"redis://user:sUpErSeCrEt@host:6379/" + "1" * 5000,
])
def test_a_rejected_url_never_carries_its_password_into_the_error(self, tmp_path, url):
(tmp_path / ".env").write_text("LLM_PROVIDER=docsgpt\n", encoding="utf-8")
with pytest.raises(DeployError) as raised:
_run(["doctor", "--dir", str(tmp_path), "--redis-url", url], _context())
message = str(raised.value)
assert self.SECRET not in message
assert "user" not in message
assert len(message) < 400, "an over-long database number must not come back in the message"
class TestDoctor:
def _only(self, monkeypatch, postgres, redis):
monkeypatch.setattr(commands, "_check_postgres", lambda uri: postgres)