new file mode 100644
@@ -0,0 +1,136 @@
+From 2dcbe838baee9938cdf4f0b7a8c682b92913bb76 Mon Sep 17 00:00:00 2001
+From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com>
+Date: Sun, 27 Sep 2026 21:27:34 +0100
+Subject: [PATCH] [PR #13830/e11d2836 backport][3.14] Fix secure shared cookie
+ (#13832)
+
+**This is a backport of PR #13830 as merged into master
+(e11d2836203a21bec59095498e578d37801027e7).**
+
+Co-authored-by: Sam Bull <git@sambull.org>
+(cherry picked from commit 999c356d61e966faffa97b06ab0d0455226d36c5)
+
+CVE: CVE-2026-111063
+Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/999c356d61e966faffa97b06ab0d0455226d36c5]
+
+Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
+---
+ CHANGES/13830.bugfix.rst | 1 +
+ aiohttp/cookiejar.py | 3 +++
+ docs/client_reference.rst | 3 ++-
+ docs/spelling_wordlist.txt | 1 +
+ tests/test_client_functional.py | 9 +++++++--
+ tests/test_cookiejar.py | 28 ++++++++++++++++++++++++++++
+ 6 files changed, 42 insertions(+), 3 deletions(-)
+ create mode 100644 CHANGES/13830.bugfix.rst
+
+diff --git a/CHANGES/13830.bugfix.rst b/CHANGES/13830.bugfix.rst
+new file mode 100644
+index 000000000..2a3976924
+--- /dev/null
++++ b/CHANGES/13830.bugfix.rst
+@@ -0,0 +1 @@
++Fixed ``CookieJar.filter_cookies()`` sending shared cookies (cookies without a ``Domain`` attribute) marked ``Secure`` over unencrypted connections -- by :user:`Dreamsorcerer`.
+diff --git a/aiohttp/cookiejar.py b/aiohttp/cookiejar.py
+index 2b9722470..0d2f3e05c 100644
+--- a/aiohttp/cookiejar.py
++++ b/aiohttp/cookiejar.py
+@@ -478,6 +478,9 @@ class CookieJar(AbstractCookieJar):
+ # Send shared cookie
+ key = ("", "")
+ for c in self._cookies[key].values():
++ if is_not_secure and c["secure"]:
++ continue
++
+ # Check cache first
+ if c.key in self._morsel_cache[key]:
+ filtered[c.key] = self._morsel_cache[key][c.key]
+diff --git a/docs/client_reference.rst b/docs/client_reference.rst
+index 734201128..a237fb64b 100644
+--- a/docs/client_reference.rst
++++ b/docs/client_reference.rst
+@@ -2544,7 +2544,8 @@ Utilities
+ :param ~yarl.URL response_url: URL of response, ``None`` for *shared
+ cookies*. Regular cookies are coupled with server's URL and
+ are sent only to this server, shared ones are sent in every
+- client request.
++ client request (except that shared cookies marked ``Secure``
++ are only sent over encrypted connections).
+
+ .. method:: filter_cookies(request_url)
+
+diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
+index 24561f52d..88638bf12 100644
+--- a/docs/spelling_wordlist.txt
++++ b/docs/spelling_wordlist.txt
+@@ -369,6 +369,7 @@ un
+ unawaited
+ unclosed
+ undercounting
++unencrypted
+ unescaped
+ unhandled
+ unicode
+diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py
+index 9470876d0..639ca4606 100644
+--- a/tests/test_client_functional.py
++++ b/tests/test_client_functional.py
+@@ -2909,12 +2909,17 @@ async def test_morsel_with_attributes(aiohttp_client) -> None:
+ c = http.cookies.Morsel()
+ c.set("test3", "456", "456")
+ c["httponly"] = True
+- c["secure"] = True
+ c["max-age"] = 1000
+
++ # A Secure shared cookie must be withheld entirely: the test server
++ # is plain http, so it must not reach the handler at all.
++ c2: http.cookies.Morsel[str] = http.cookies.Morsel()
++ c2.set("test4", "789", "789")
++ c2["secure"] = True
++
+ app = web.Application()
+ app.router.add_get("/", handler)
+- client = await aiohttp_client(app, cookies={"test2": c})
++ client = await aiohttp_client(app, cookies={"test2": c, "test4": c2})
+
+ async with client.get("/") as resp:
+ assert 200 == resp.status
+diff --git a/tests/test_cookiejar.py b/tests/test_cookiejar.py
+index 9276ff252..9f279801b 100644
+--- a/tests/test_cookiejar.py
++++ b/tests/test_cookiejar.py
+@@ -1206,6 +1206,34 @@ async def test_treat_as_secure_origin() -> None:
+ assert len(filtered_cookies) == 1
+
+
++async def test_treat_as_secure_origin_sends_secure_shared_cookie() -> None:
++ endpoint = URL("http://127.0.0.1/")
++
++ jar = CookieJar(unsafe=True, treat_as_secure_origin=[endpoint])
++ jar.update_cookies(SimpleCookie("shared-secure-cookie=first; Secure;"))
++
++ filtered_cookies = jar.filter_cookies(request_url=endpoint)
++ assert "shared-secure-cookie" in filtered_cookies
++
++
++async def test_filter_cookies_with_secure_shared_cookie() -> None:
++ """Secure shared cookies (no Domain attribute) must not be sent over cleartext."""
++ jar = CookieJar()
++ jar.update_cookies(
++ SimpleCookie("shared-secure-cookie=first; Secure; shared-cookie=second;")
++ )
++
++ filtered = jar.filter_cookies(URL("http://example.com/"))
++ assert set(filtered.keys()) == {"shared-cookie"}
++
++ filtered = jar.filter_cookies(URL("https://example.com/"))
++ assert set(filtered.keys()) == {"shared-cookie", "shared-secure-cookie"}
++
++ # The morsel cached by the https request must not bypass the Secure check.
++ filtered = jar.filter_cookies(URL("http://example.com/"))
++ assert set(filtered.keys()) == {"shared-cookie"}
++
++
+ async def test_filter_cookies_does_not_leak_memory() -> None:
+ """Test that filter_cookies doesn't create empty cookie entries.
+
@@ -6,6 +6,8 @@ LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=b5e9e27554f71f0f132919037cb967b2"
SRC_URI[sha256sum] = "9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc"
+SRC_URI += "file://CVE-2026-111063.patch"
+
CVE_PRODUCT = "aiohttp:aiohttp"
CVE_STATUS_GROUPS = "CVE_AIOHTTP_FIX_3_13_4"
CVE_AIOHTTP_FIX_3_13_4[status] = "fixed-version: fixed in 3.13.4"