diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-54280.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-54280.patch
new file mode 100644
index 0000000000..c598a5194c
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-54280.patch
@@ -0,0 +1,138 @@
+From 724ae4d652417c4490a71ea0b16b8804dad3004f Mon Sep 17 00:00:00 2001
+From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com>
+Date: Sun, 7 Jun 2026 05:47:16 +0000
+Subject: [PATCH] [PR #12831/1ac92dae backport][3.14] Payload close on
+ disconnect (#12843)
+
+CVE: CVE-2026-54280
+Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/a762eda5242f6490d6ba667533193f8b473ad587]
+
+Co-authored-by: J. Nick Koston <nick@koston.org>
+(cherry picked from commit a762eda5242f6490d6ba667533193f8b473ad587)
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ CHANGES/12831.bugfix.rst   |  1 +
+ aiohttp/web_response.py    |  6 ++--
+ tests/test_web_response.py | 73 +++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 77 insertions(+), 3 deletions(-)
+ create mode 100644 CHANGES/12831.bugfix.rst
+
+diff --git a/CHANGES/12831.bugfix.rst b/CHANGES/12831.bugfix.rst
+new file mode 100644
+index 000000000..bf460ffcc
+--- /dev/null
++++ b/CHANGES/12831.bugfix.rst
+@@ -0,0 +1 @@
++Fixed :meth:`aiohttp.web.Response.write_eof` skipping ``Payload.close()`` when the body write was interrupted by an error or cancellation, for example when a client disconnects mid-response; the payload close hook now runs in a ``finally`` so a :class:`~aiohttp.payload.Payload` body always releases its resources -- by :user:`bdraco`.
+diff --git a/aiohttp/web_response.py b/aiohttp/web_response.py
+index 364270e4d..cea5d4b45 100644
+--- a/aiohttp/web_response.py
++++ b/aiohttp/web_response.py
+@@ -779,8 +779,10 @@ class Response(StreamResponse):
+         if body is None or self._must_be_empty_body:
+             await super().write_eof()
+         elif isinstance(self._body, Payload):
+-            await self._body.write(self._payload_writer)
+-            await self._body.close()
++            try:
++                await self._body.write(self._payload_writer)
++            finally:
++                await self._body.close()
+             await super().write_eof()
+         else:
+             await super().write_eof(cast(bytes, body))
+diff --git a/tests/test_web_response.py b/tests/test_web_response.py
+index 5a4fb7e66..f094cd3d2 100644
+--- a/tests/test_web_response.py
++++ b/tests/test_web_response.py
+@@ -1,3 +1,4 @@
++import asyncio
+ import collections.abc
+ import datetime
+ import gzip
+@@ -18,7 +19,7 @@ from aiohttp.abc import AbstractStreamWriter
+ from aiohttp.helpers import ETag
+ from aiohttp.http_writer import StreamWriter, _serialize_headers
+ from aiohttp.multipart import BodyPartReader, MultipartWriter
+-from aiohttp.payload import BytesPayload, StringPayload
++from aiohttp.payload import BytesPayload, Payload, StringPayload
+ from aiohttp.test_utils import make_mocked_request
+ from aiohttp.web import ContentCoding, Response, StreamResponse, json_response
+ 
+@@ -1370,6 +1371,76 @@ async def test_consecutive_write_eof() -> None:
+     writer.write_eof.assert_called_once_with(data)
+ 
+ 
++class _ClosingPayload(Payload):
++    """Payload test double that records whether close() ran."""
++
++    def __init__(self) -> None:
++        super().__init__(None)
++        self.close_called = False
++        self.started = asyncio.Event()
++        self.release = asyncio.Event()
++        self.fail = False
++
++    async def write(self, writer: AbstractStreamWriter) -> None:
++        self.started.set()
++        if self.fail:
++            raise ConnectionResetError("client gone")
++        await self.release.wait()
++
++    async def close(self) -> None:
++        self.close_called = True
++        await super().close()
++
++    def decode(self, encoding: str = "utf-8", errors: str = "strict") -> str:
++        assert False
++
++
++async def test_write_eof_closes_payload_on_success() -> None:
++    writer = mock.create_autospec(AbstractStreamWriter, spec_set=True, instance=True)
++    req = make_request("GET", "/", writer=writer)
++    payload = _ClosingPayload()
++    payload.release.set()
++    resp = web.Response(body=payload)
++
++    await resp.prepare(req)
++    await resp.write_eof()
++
++    assert payload.close_called
++    assert writer.write_eof.called
++
++
++async def test_write_eof_closes_payload_on_write_error() -> None:
++    writer = mock.create_autospec(AbstractStreamWriter, spec_set=True, instance=True)
++    req = make_request("GET", "/", writer=writer)
++    payload = _ClosingPayload()
++    payload.fail = True
++    resp = web.Response(body=payload)
++
++    await resp.prepare(req)
++    with pytest.raises(ConnectionResetError):
++        await resp.write_eof()
++
++    assert payload.close_called
++    assert not writer.write_eof.called
++
++
++async def test_write_eof_closes_payload_on_cancel() -> None:
++    writer = mock.create_autospec(AbstractStreamWriter, spec_set=True, instance=True)
++    req = make_request("GET", "/", writer=writer)
++    payload = _ClosingPayload()
++    resp = web.Response(body=payload)
++
++    await resp.prepare(req)
++    task = asyncio.ensure_future(resp.write_eof())
++    await payload.started.wait()
++    task.cancel()
++    with pytest.raises(asyncio.CancelledError):
++        await task
++
++    assert payload.close_called
++    assert not writer.write_eof.called
++
++
+ def test_set_text_with_content_type() -> None:
+     resp = Response()
+     resp.content_type = "text/html"
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 9102175f24..b9d08ac97b 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
@@ -16,6 +16,7 @@ SRC_URI += " \
     file://CVE-2026-54277.patch \
     file://CVE-2026-54278.patch \
     file://CVE-2026-54279.patch \
+    file://CVE-2026-54280.patch \
 "
 
 CVE_PRODUCT = "aiohttp"
