{"id":"GHSA-jm3w-gw2p-xjfj","kind":"vulnerability","aliases":["GHSA-jm3w-gw2p-xjfj"],"related":[],"title":"Event loop stall in add_domain() wildcard matching","description":"### Summary\r\n\r\n`Application.add_domain()` compiled each `*` in a host mask to `[^:]*`. With two or more wildcards in a mask, matching a long `Host` header that does not match the mask took polynomial time on the event loop.\r\n\r\n### Impact\r\n\r\nAn attacker could stall a server that registers a domain mask with more than one wildcard by sending requests with a long `Host` header.\r\n\r\n### Workaround\r\n\r\nUse at most one `*` in a domain mask.\r\n\r\n---\r\n\r\nPatch: https://github.com/aio-libs/aiohttp/commit/c6ac0e44c3c573ff9616f4a6a532992538b31e43","summary":"aiohttp's add_domain() compiled each wildcard in a host mask to a pattern that backtracks badly. With two or more wildcards, a long Host header that does not match the mask takes polynomial time to reject, blocking the event loop.","severity":"low","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"aiohttp","fixed":["3.14.4"],"affected":"<= 3.14.3","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["aiohttp","cwe-1333","package","python","web-servers"],"not_affected_if":["no-add-domain","single-wildcard-masks"],"how_to_check":"- `pip show aiohttp` to read the installed version\n- Search application code for `add_domain(` and count `*` characters in each mask string\n- Check whether the app is publicly reachable and accepts arbitrary Host headers","fix":"- aiohttp: move to `3.14.4` or later","status":"open","published_at":"2026-11-08T18:51:53+00:00","first_seen_at":"2026-11-09T22:53:22+00:00","triaged_at":"2026-11-09T22:58:31+00:00","updated_at":"2026-11-09T22:58:31+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-09T22:58:31Z","model":"claude-haiku-5-5","output":{"fix":"- aiohttp: move to `3.14.4` or later","reach":"internet","title":"aiohttp: wildcard domain masks can stall the event loop on long Host headers","impact":"low","summary":"aiohttp's add_domain() compiled each wildcard in a host mask to a pattern that backtracks badly. With two or more wildcards, a long Host header that does not match the mask takes polynomial time to reject, blocking the event loop.","audience":"developers","category":"package","nicknames":[],"who_cares":["python","aiohttp","web-servers"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"server event loop stalls, causing denial of service","analyst_note":"","how_to_check":"- `pip show aiohttp` to read the installed version\n- Search application code for `add_domain(` and count `*` characters in each mask string\n- Check whether the app is publicly reachable and accepts arbitrary Host headers","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-add-domain","single-wildcard-masks"],"who_is_affected":"Only applications that call Application.add_domain() with a host mask containing two or more `*` wildcards are exposed. An attacker must send requests with long Host headers to a server that does so. Apps that do not use add_domain() or use at most one wildcard per mask can skip it.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"low"},"cost_usd":0.000723,"input_tokens":4712,"output_tokens":503,"severity_before":"low"},"analyst_status":null,"analyst_note":null,"search":"'-1333':22B '/aio-libs/aiohttp/commit/c6ac0e44c3c573ff9616f4a6a532992538b31e43':142C 'add':5A,30B 'aiohttp':19A,20B,28B 'application.add':70C 'attack':107C 'backtrack':43B 'bad':44B 'block':65B 'compil':32B,72C 'could':108C 'cwe':21B 'domain':6A,31B,71C,115C,137C 'event':1A,67B,103C 'ghsa':10A,15A 'ghsa-jm3w-gw2p-xjfj':9A,14A 'github.com':141C 'github.com/aio-libs/aiohttp/commit/c6ac0e44c3c573ff9616f4a6a532992538b31e43':140C 'gw2p':12A,17A 'header':53B,91C,129C 'host':37B,52B,76C,90C,128C 'impact':105C 'jm3w':11A,16A 'long':51B,89C,127C 'loop':2A,68B,104C 'mask':38B,59B,77C,86C,97C,116C,138C 'match':8A,57B,87C,95C 'one':120C,134C 'packag':23B 'patch':139C 'pattern':41B 'polynomi':61B,99C 'python':24B 'regist':113C 'reject':64B 'request':124C 'send':123C 'server':27B,111C 'stall':3A,109C 'summari':69C 'take':60B 'time':62B,100C 'took':98C 'two':46B,80C 'use':131C 'web':26B 'web-serv':25B 'wildcard':7A,34B,49B,83C,121C 'workaround':130C 'xjfj':13A,18A","nicknames":[],"mitigations":[],"who_affected":"Only applications that call Application.add_domain() with a host mask containing two or more `*` wildcards are exposed. An attacker must send requests with long Host headers to a server that does so. Apps that do not use add_domain() or use at most one wildcard per mask can skip it.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["aiohttp"],"ptokens":["aiohttp"],"labels":["aiohttp","cwe1333","low","package","pypi","python","webservers"],"campaign_type":null,"search_a":"'add':5A 'aiohttp':19A 'domain':6A 'event':1A 'ghsa':10A,15A 'ghsa-jm3w-gw2p-xjfj':9A,14A 'gw2p':12A,17A 'jm3w':11A,16A 'loop':2A 'match':8A 'stall':3A 'wildcard':7A 'xjfj':13A,18A","search_b":"'-1333':22B 'add':30B 'aiohttp':20B,28B 'backtrack':43B 'bad':44B 'block':65B 'compil':32B 'cwe':21B 'domain':31B 'event':67B 'header':53B 'host':37B,52B 'long':51B 'loop':68B 'mask':38B,59B 'match':57B 'packag':23B 'pattern':41B 'polynomi':61B 'python':24B 'reject':64B 'server':27B 'take':60B 'time':62B 'two':46B 'web':26B 'web-serv':25B 'wildcard':34B,49B","search_c":"'/aio-libs/aiohttp/commit/c6ac0e44c3c573ff9616f4a6a532992538b31e43':142C 'application.add':70C 'attack':107C 'compil':72C 'could':108C 'domain':71C,115C,137C 'event':103C 'github.com':141C 'github.com/aio-libs/aiohttp/commit/c6ac0e44c3c573ff9616f4a6a532992538b31e43':140C 'header':91C,129C 'host':76C,90C,128C 'impact':105C 'long':89C,127C 'loop':104C 'mask':77C,86C,97C,116C,138C 'match':87C,95C 'one':120C,134C 'patch':139C 'polynomi':99C 'regist':113C 'request':124C 'send':123C 'server':111C 'stall':109C 'summari':69C 'time':100C 'took':98C 'two':80C 'use':131C 'wildcard':83C,121C 'workaround':130C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-08T18:51:53+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-jm3w-gw2p-xjfj","url":"https://github.com/aio-libs/aiohttp/security/advisories/GHSA-jm3w-gw2p-xjfj","severity":"low","published_at":"2026-11-08T18:51:53+00:00","modified_at":"2026-11-08T18:51:53+00:00","first_seen_at":"2026-11-09T22:53:22+00:00","fetched_at":"2026-11-09T22:53:22+00:00","note":null}],"documents":[{"id":110551,"url":"https://github.com/aio-libs/aiohttp/security/advisories/GHSA-jm3w-gw2p-xjfj","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}