diff --git a/meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54058.patch b/meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54058.patch
new file mode 100644
index 0000000000..6fc38570ee
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54058.patch
@@ -0,0 +1,89 @@
+From 04410f2e38c070e6d519c24d1cf315612b8adb93 Mon Sep 17 00:00:00 2001
+From: Andrew Murray <3112309+radarhere@users.noreply.github.com>
+Date: Fri, 26 Jun 2026 07:35:42 +1000
+Subject: [PATCH] Ensure map stride is at least one full row of pixels (#9719)
+
+CVE: CVE-2026-54058
+Upstream-Status: Backport [https://github.com/python-pillow/Pillow/commit/6a8de891fb00968e5ea79bfa84368ed90b3cfc1d]
+Signed-off-by: Aravind Bandari <aravind.bandari@windriver.com>
+
+Co-authored-by: GameZoneHacker <devanshshah2003@hotmail.com>
+---
+ Tests/test_file_mcidas.py | 25 +++++++++++++++++++++++++
+ src/map.c                 | 18 ++++++++++--------
+ 2 files changed, 35 insertions(+), 8 deletions(-)
+
+diff --git a/Tests/test_file_mcidas.py b/Tests/test_file_mcidas.py
+index 7e236028d..d1410f503 100644
+--- a/Tests/test_file_mcidas.py
++++ b/Tests/test_file_mcidas.py
+@@ -1,5 +1,8 @@
+ from __future__ import annotations
+ 
++import struct
++from pathlib import Path
++
+ import pytest
+ 
+ from PIL import Image, McIdasImagePlugin
+@@ -14,6 +17,28 @@ def test_invalid_file() -> None:
+         McIdasImagePlugin.McIdasImageFile(invalid_file)
+ 
+ 
++def test_undersized_stride(tmp_path: Path) -> None:
++    # A crafted area descriptor declares a row stride far smaller than a full
++    # row of pixels. Memory mapping must not lay out row pointers at that
++    # stride, which would read past the mapped buffer; the image is rejected
++    # instead of leaking memory or crashing.
++    words = [0] * 65
++    words[2] = 4  # magic: 00 00 00 00 00 00 00 04
++    words[9] = 1  # ysize
++    words[10] = 200000  # xsize -> a full row is 200000 bytes (mode "L")
++    words[11] = 1  # mode "L"
++    words[14] = 0  # zeroes the xsize term of the stride
++    words[15] = 1  # stride = 1  (much smaller than a row)
++    data = struct.pack("!64i", *words[1:65])
++
++    path = tmp_path / "undersized_stride.area"
++    path.write_bytes(data)
++
++    with Image.open(path) as im:
++        with pytest.raises(ValueError, match="buffer is not large enough"):
++            im.load()
++
++
+ def test_valid_file() -> None:
+     # Arrange
+     # https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8
+diff --git a/src/map.c b/src/map.c
+index 6f66b0cc5..4c9bb2ae3 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -84,14 +84,16 @@ PyImaging_MapBuffer(PyObject *self, PyObject *args) {
+ 
+     const ModeID mode = findModeID(mode_name);
+ 
+-    if (stride <= 0) {
+-        if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) {
+-            stride = xsize;
+-        } else if (isModeI16(mode)) {
+-            stride = xsize * 2;
+-        } else {
+-            stride = xsize * 4;
+-        }
++    int pixelsize;
++    if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) {
++        pixelsize = 1;
++    } else if (isModeI16(mode)) {
++        pixelsize = 2;
++    } else {
++        pixelsize = 4;
++    }
++    if (stride <= xsize * pixelsize) {
++        stride = xsize * pixelsize;
+     }
+ 
+     if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {
+-- 
+2.53.0
+
diff --git a/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb b/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb
index f3fcb2d3c1..29a65dd148 100644
--- a/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb
+++ b/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb
@@ -7,6 +7,7 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=a6f0ac3777cfc96ded1b825e32ae7c99"
 
 SRC_URI = "git://github.com/python-pillow/Pillow.git;branch=main;protocol=https;tag=${PV} \
            file://0001-support-cross-compiling.patch \
+           file://CVE-2026-54058.patch \
            "
 SRCREV = "3c41c095064200a02672d89cc5ff629eaf4b0d4f"
 
