diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-59881.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-59881.patch new file mode 100644 index 0000000000..14b05cd2fa --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-59881.patch @@ -0,0 +1,103 @@ +From b052f95658821f726388cb86cfefad1cec264842 Mon Sep 17 00:00:00 2001 +From: Sam Bull +Date: Thu, 1 Oct 2026 02:37:30 -0700 +Subject: [PATCH] Fix decompressing frames without negotiation (#12976) + (#12978) + +CVE: CVE-2026-59881 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/47fb6ae354d4fa22048f4dbe7dbf82b625f0a2f6] + +Backport Changes: +- Passed the negotiated compression flag to the 3.13.5 client reader. +- Kept the reader's compress=True default: both production call + sites now pass the negotiated setting (the server already did). +- Adapted the upstream client regression test to the 3.13.5 API. +- Omitted changes to newer WebSocket APIs and unrelated tests. + +(cherry picked from commit 47fb6ae354d4fa22048f4dbe7dbf82b625f0a2f6) +Signed-off-by: Darsh Kelaiya +--- + aiohttp/client.py | 4 ++- + tests/test_client_ws_functional.py | 40 +++++++++++++++++++++++++++++- + 2 files changed, 42 insertions(+), 2 deletions(-) + +diff --git a/aiohttp/client.py b/aiohttp/client.py +index 0637eff6b..8cd9add5f 100644 +--- a/aiohttp/client.py ++++ b/aiohttp/client.py +@@ -1190,7 +1190,9 @@ class ClientSession: + transport = conn.transport + assert transport is not None + reader = WebSocketDataQueue(conn_proto, 2**16, loop=self._loop) +- conn_proto.set_parser(WebSocketReader(reader, max_msg_size), reader) ++ conn_proto.set_parser( ++ WebSocketReader(reader, max_msg_size, compress=bool(compress)), reader ++ ) + writer = WebSocketWriter( + conn_proto, + transport, +diff --git a/tests/test_client_ws_functional.py b/tests/test_client_ws_functional.py +index 7b6bd0322..a67769c1c 100644 +--- a/tests/test_client_ws_functional.py ++++ b/tests/test_client_ws_functional.py +@@ -1,5 +1,7 @@ + import asyncio ++import struct + import sys ++import zlib + from typing import Any, List, NoReturn, Optional + from unittest import mock + +@@ -15,8 +17,9 @@ from aiohttp import ( + web, + ) + from aiohttp._websocket.reader import WebSocketDataQueue ++from aiohttp._websocket.models import WS_DEFLATE_TRAILING + from aiohttp.client_ws import ClientWSTimeout +-from aiohttp.http import WSCloseCode ++from aiohttp.http import WebSocketError, WSCloseCode + from aiohttp.pytest_plugin import AiohttpClient + + if sys.version_info >= (3, 11): +@@ -1276,3 +1279,38 @@ async def test_websocket_connection_cancellation( + # Cleanup properly + websocket._response = mock.Mock() + await websocket.close() ++ ++ ++async def test_client_rejects_compressed_frame_without_negotiation( ++ aiohttp_client: AiohttpClient, ++) -> None: ++ """Reject RSV1 frames when permessage-deflate was not negotiated.""" ++ payload = b"this frame should never be decompressed by the client" ++ ++ async def handler(request: web.Request) -> web.WebSocketResponse: ++ ws = web.WebSocketResponse() ++ await ws.prepare(request) ++ transport = request.transport ++ assert transport is not None ++ compressor = zlib.compressobj( ++ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS ++ ) ++ compressed = compressor.compress(payload) ++ compressed += compressor.flush(zlib.Z_SYNC_FLUSH) ++ compressed = compressed.removesuffix(WS_DEFLATE_TRAILING) ++ frame = struct.pack("!BB", 0x80 | 0x40 | WSMsgType.TEXT.value, ++ len(compressed)) + compressed ++ transport.write(frame) ++ await ws.receive() ++ return ws ++ ++ app = web.Application() ++ app.router.add_get("/", handler) ++ client = await aiohttp_client(app) ++ async with client.ws_connect("/") as ws: ++ assert ws.compress == 0 ++ msg = await ws.receive() ++ ++ assert msg.type is WSMsgType.ERROR, msg ++ assert isinstance(msg.data, WebSocketError) ++ assert msg.data.code == WSCloseCode.PROTOCOL_ERROR +-- +2.35.6 + diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.13.5.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.13.5.bb index 0faf2a8d74..b34a0fa3eb 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.13.5.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.13.5.bb @@ -19,6 +19,7 @@ SRC_URI += " \ file://CVE-2026-54280.patch \ file://CVE-2026-54273_p1.patch \ file://CVE-2026-54273_p2.patch \ + file://CVE-2026-59881.patch \ " CVE_PRODUCT = "aiohttp:aiohttp"