From e96529b7722ab13de7d4088bc533d37863603e6b Mon Sep 17 00:00:00 2001 From: pr-relay Date: Sun, 16 Aug 2026 12:48:50 +0000 Subject: [PATCH 1/3] fix: handle missing cleartext password cleanly --- asyncpg/protocol/coreproto.pyx | 10 ++++++++-- tests/test_connect.py | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/asyncpg/protocol/coreproto.pyx b/asyncpg/protocol/coreproto.pyx index da96c412..5470d6fa 100644 --- a/asyncpg/protocol/coreproto.pyx +++ b/asyncpg/protocol/coreproto.pyx @@ -573,8 +573,14 @@ cdef class CoreProtocol: elif status == AUTH_REQUIRED_PASSWORD: # AuthenticationCleartextPassword - self.result_type = RESULT_OK - self.auth_msg = self._auth_password_message_cleartext() + if self.password is None: + self.result_type = RESULT_FAILED + self.result = apg_exc.InterfaceError( + 'password authentication requested by server, ' + 'but no password was supplied') + else: + self.result_type = RESULT_OK + self.auth_msg = self._auth_password_message_cleartext() elif status == AUTH_REQUIRED_PASSWORDMD5: # AuthenticationMD5Password diff --git a/tests/test_connect.py b/tests/test_connect.py index 955fb825..ba6ac0ea 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -266,6 +266,12 @@ async def test_auth_password_cleartext(self): user='password_user', password='wrongpassword') + async def test_auth_password_cleartext_without_password(self): + with self.assertRaisesRegex( + asyncpg.InterfaceError, 'no password was supplied'): + await self._try_connect( + user='password_user', password=None) + async def test_auth_password_cleartext_callable(self): def get_correctpassword(): return CORRECT_PASSWORD From 8f79fba9f2ab3e81647acb42e90b69ee6f629b0b Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 23 Sep 2026 18:35:33 -0700 Subject: [PATCH 2/3] test: isolate missing cleartext password case --- tests/test_connect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_connect.py b/tests/test_connect.py index 6dab6a29..a0d6779f 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -274,7 +274,7 @@ async def test_auth_password_cleartext_without_password(self): with self.assertRaisesRegex( asyncpg.InterfaceError, 'no password was supplied'): await self._try_connect( - user='password_user', password=None) + user='password_user', password=lambda: None) async def test_auth_password_cleartext_callable(self): def get_correctpassword(): From 29214e01ae0562451a562a0ef1cb765a3345dc1b Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 23 Sep 2026 19:26:40 -0700 Subject: [PATCH 3/3] fix: report missing cleartext password as authentication failure --- asyncpg/protocol/coreproto.pyx | 12 +++--------- tests/test_connect.py | 3 +-- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/asyncpg/protocol/coreproto.pyx b/asyncpg/protocol/coreproto.pyx index 34f10d26..d5936c7a 100644 --- a/asyncpg/protocol/coreproto.pyx +++ b/asyncpg/protocol/coreproto.pyx @@ -579,14 +579,8 @@ cdef class CoreProtocol: elif status == AUTH_REQUIRED_PASSWORD: # AuthenticationCleartextPassword - if self.password is None: - self.result_type = RESULT_FAILED - self.result = apg_exc.InterfaceError( - 'password authentication requested by server, ' - 'but no password was supplied') - else: - self.result_type = RESULT_OK - self.auth_msg = self._auth_password_message_cleartext() + self.result_type = RESULT_OK + self.auth_msg = self._auth_password_message_cleartext() elif status == AUTH_REQUIRED_PASSWORDMD5: # AuthenticationMD5Password @@ -681,7 +675,7 @@ cdef class CoreProtocol: WriteBuffer msg msg = WriteBuffer.new_message(b'p') - msg.write_bytestring(self.password.encode(self.encoding)) + msg.write_bytestring((self.password or '').encode(self.encoding)) msg.end_message() return msg diff --git a/tests/test_connect.py b/tests/test_connect.py index a0d6779f..e00c7b6c 100644 --- a/tests/test_connect.py +++ b/tests/test_connect.py @@ -271,8 +271,7 @@ async def test_auth_password_cleartext(self): password='wrongpassword') async def test_auth_password_cleartext_without_password(self): - with self.assertRaisesRegex( - asyncpg.InterfaceError, 'no password was supplied'): + with self.assertRaises(asyncpg.InvalidPasswordError): await self._try_connect( user='password_user', password=lambda: None)