From 67e2e4900b7fd7645ca786064579f2916eaecb2e Mon Sep 17 00:00:00 2001 From: Guillaume BAILLEUL Date: Fri, 2 Oct 2026 11:33:23 +0200 Subject: [PATCH] Fix 500 instead of 401 when reverse DNS lookup fails to decode (#182919) Co-authored-by: Claude Sonnet 5 Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- homeassistant/components/http/ban.py | 2 +- tests/components/http/test_ban.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/http/ban.py b/homeassistant/components/http/ban.py index c9f6cab2c888..f05911ba8952 100644 --- a/homeassistant/components/http/ban.py +++ b/homeassistant/components/http/ban.py @@ -119,7 +119,7 @@ async def process_wrong_login(request: Request) -> None: assert request.remote remote_addr = ip_address(request.remote) remote_host = request.remote - with suppress(herror): + with suppress(herror, UnicodeDecodeError): remote_host, _, _ = await hass.async_add_executor_job( gethostbyaddr, request.remote ) diff --git a/tests/components/http/test_ban.py b/tests/components/http/test_ban.py index 58498d99f521..df11d862818c 100644 --- a/tests/components/http/test_ban.py +++ b/tests/components/http/test_ban.py @@ -4,6 +4,7 @@ from http import HTTPStatus from ipaddress import ip_address import logging import os +from typing import NoReturn from unittest.mock import AsyncMock, Mock, mock_open, patch from aiohttp import web @@ -462,6 +463,33 @@ async def test_failed_login_attempts_counter( assert app[KEY_FAILED_LOGIN_ATTEMPTS][remote_ip] == 2 +async def test_failed_login_attempts_counter_reverse_dns_unicode_decode_error( + hass: HomeAssistant, aiohttp_client: ClientSessionGenerator +) -> None: + """Test a wrong login still gets a 401 if the reverse DNS lookup fails to decode.""" + app = web.Application() + app[KEY_HASS] = hass + + async def unauth_handler(request: web.Request) -> NoReturn: + """Return a mock web response.""" + raise HTTPUnauthorized + + app.router.add_get("/example", unauth_handler) + setup_bans(hass, app, 5) + remote_ip = ip_address("200.201.202.204") + mock_real_ip(app)("200.201.202.204") + + with patch( + "homeassistant.components.http.ban.gethostbyaddr", + side_effect=UnicodeDecodeError("utf-8", b"\x8a", 0, 1, "invalid start byte"), + ): + client = await aiohttp_client(app) + resp = await client.get("/example") + + assert resp.status == HTTPStatus.UNAUTHORIZED + assert app[KEY_FAILED_LOGIN_ATTEMPTS][remote_ip] == 1 + + async def test_single_ban_file_entry( hass: HomeAssistant, ) -> None: