diff --git a/meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88052.patch b/meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88052.patch
new file mode 100644
index 0000000000..fb21f6eb02
--- /dev/null
+++ b/meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88052.patch
@@ -0,0 +1,165 @@
+From 26355d536f148a45a43cfe8b5b5f4a748d99fe8e Mon Sep 17 00:00:00 2001
+From: Stefan Weil <sw@weilnetz.de>
+Date: Fri, 21 Aug 2026 18:34:33 +0200
+Subject: [PATCH] Reject unicharset files whose inserts desync id from unichars
+
+UNICHARSET::load_via_fgets reads the unichar count via sscanf and
+trusts it as the loop bound, indexing the unichars vector with the
+loop index id via the unchecked set_* accessors. unichar_insert is a
+no-op for duplicate (or empty) representations, so once any insert
+no-ops, unichars.size() falls behind id and the subsequent
+set_*(id, ...) and unichars[id].properties writes land past the end
+of the vector - a deterministic heap out-of-bounds write (including a
+std::string assignment via set_normed) for every remaining line, on
+both the LSTM and legacy init paths. A malformed unicharset with a
+duplicate line (e.g. two identical entries) triggers it; a
+non-positive header count likewise loads an empty unicharset
+"successfully".
+
+Key changes:
+- unicharset.cpp: reject unicharset_size <= 0, and after each insert
+  verify the vector actually grew to id + 1; on mismatch report the
+  offending line and reject the file instead of writing out of bounds.
+- unittest: add unicharset_load_test with a duplicate-representation
+  unicharset (on unpatched code the test dies on the
+  container-overflow in load_via_fgets), a zero and a negative count,
+  and a positive control that a valid unicharset still loads.
+
+Reported-by: Zhixi "Jace" Sun <g.mygenie@gmail.com>
+Assisted-by: OpenCode / qwen3.8-27b-thinking (Alibaba Cloud)
+Signed-off-by: Stefan Weil <sw@weilnetz.de>
+(cherry picked from commit 2d04d640db2e8c7e3bab2369d599343b5a8b8443)
+
+CVE: CVE-2026-88052
+Upstream-Status: Backport [https://github.com/tesseract-ocr/tesseract/commit/2d04d640db2e8c7e3bab2369d599343b5a8b8443]
+Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
+---
+ Makefile.am                      |  5 +++
+ src/ccutil/unicharset.cpp        | 12 ++++++
+ unittest/unicharset_load_test.cc | 64 ++++++++++++++++++++++++++++++++
+ 3 files changed, 81 insertions(+)
+ create mode 100644 unittest/unicharset_load_test.cc
+
+diff --git a/Makefile.am b/Makefile.am
+index 9f2a367d..1a0a6771 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1249,6 +1249,7 @@ check_PROGRAMS += tfile_test
+ if ENABLE_TRAINING
+ check_PROGRAMS += unichar_test
+ check_PROGRAMS += unicharcompress_test
++check_PROGRAMS += unicharset_load_test
+ check_PROGRAMS += unicharset_test
+ check_PROGRAMS += validate_grapheme_test
+ check_PROGRAMS += validate_indic_test
+@@ -1522,6 +1523,10 @@ unicharcompress_test_SOURCES = unittest/unicharcompress_test.cc
+ unicharcompress_test_CPPFLAGS = $(unittest_CPPFLAGS)
+ unicharcompress_test_LDADD = $(TRAINING_LIBS) $(ICU_UC_LIBS)
+ 
++unicharset_load_test_SOURCES = unittest/unicharset_load_test.cc
++unicharset_load_test_CPPFLAGS = $(unittest_CPPFLAGS)
++unicharset_load_test_LDADD = $(TESS_LIBS)
++
+ unicharset_test_SOURCES = unittest/unicharset_test.cc
+ unicharset_test_CPPFLAGS = $(unittest_CPPFLAGS)
+ unicharset_test_LDADD = $(TRAINING_LIBS) $(ICU_UC_LIBS)
+diff --git a/src/ccutil/unicharset.cpp b/src/ccutil/unicharset.cpp
+index b29ec3b7..0e72ae48 100644
+--- a/src/ccutil/unicharset.cpp
++++ b/src/ccutil/unicharset.cpp
+@@ -791,6 +791,9 @@ bool UNICHARSET::load_via_fgets(
+       sscanf(buffer, "%d", &unicharset_size) != 1) {
+     return false;
+   }
++  if (unicharset_size <= 0) {
++    return false;
++  }
+   for (UNICHAR_ID id = 0; id < unicharset_size; ++id) {
+     char unichar[256];
+     unsigned int properties;
+@@ -884,6 +887,15 @@ bool UNICHARSET::load_via_fgets(
+     } else {
+       this->unichar_insert_backwards_compatible(unichar);
+     }
++    // A duplicate or empty representation makes the insert a no-op,
++    // desynchronizing id from the unichars vector; the set_* calls and
++    // unichars[id] below would then write out of bounds. The file is
++    // malformed, so reject it.
++    if (size() != static_cast<size_t>(id) + 1) {
++      fprintf(stderr, "%s:%d unichar %d has a duplicate or empty representation\n",
++              __FILE__, __LINE__, id);
++      return false;
++    }
+ 
+     this->set_isalpha(id, properties & ISALPHA_MASK);
+     this->set_islower(id, properties & ISLOWER_MASK);
+diff --git a/unittest/unicharset_load_test.cc b/unittest/unicharset_load_test.cc
+new file mode 100644
+index 00000000..d775e233
+--- /dev/null
++++ b/unittest/unicharset_load_test.cc
+@@ -0,0 +1,64 @@
++///////////////////////////////////////////////////////////////////////
++// File:        unicharset_load_test.cc
++// Description: Tests that UNICHARSET::load_via_fgets rejects unicharset
++//              files whose insertions desynchronize the id loop index
++//              from the unichars vector (duplicate or empty
++//              representations), which would make the subsequent set_*
++//              calls write out of bounds, and non-positive size counts.
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++///////////////////////////////////////////////////////////////////////
++
++#include "include_gunit.h"
++
++#include "serialis.h" // for TFile
++#include "unicharset.h"
++
++#include <cstring>
++
++namespace tesseract {
++namespace {
++
++// Loads the given unicharset text via the TFile-based loader.
++bool LoadUnicharset(const char *text, UNICHARSET *unicharset) {
++  TFile fp;
++  if (!fp.Open(text, std::strlen(text))) {
++    return false;
++  }
++  return unicharset->load_from_file(&fp, false);
++}
++
++// A duplicate representation makes the second insert a no-op, so on
++// unpatched code the set_* calls for the remaining lines write past
++// the end of the unichars vector (ASan container-overflow).
++TEST(UnicharsetLoadTest, RejectsDuplicateRepresentation) {
++  const char *text = "3\nA 0 Latin\nA 0 Latin\nB 0 Latin\n";
++  UNICHARSET unicharset;
++  EXPECT_FALSE(LoadUnicharset(text, &unicharset));
++}
++
++// A non-positive size count must be rejected; on unpatched code a
++// zero or negative count loads an empty unicharset successfully.
++TEST(UnicharsetLoadTest, RejectsNonPositiveCount) {
++  const char *texts[] = {"0\n", "-1\n"};
++  for (const char *text : texts) {
++    UNICHARSET unicharset;
++    EXPECT_FALSE(LoadUnicharset(text, &unicharset));
++  }
++}
++
++// A valid unicharset must still be accepted.
++TEST(UnicharsetLoadTest, AcceptsValidUnicharset) {
++  const char *text = "3\nA 0 Latin\nB 0 Latin\nC 0 Latin\n";
++  UNICHARSET unicharset;
++  ASSERT_TRUE(LoadUnicharset(text, &unicharset));
++  EXPECT_EQ(unicharset.size(), 3u);
++  EXPECT_STREQ(unicharset.id_to_unichar(1), "B");
++}
++
++} // namespace
++} // namespace tesseract
diff --git a/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb b/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb
index f26d2f36a1..a80407b749 100644
--- a/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb
+++ b/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb
@@ -10,6 +10,7 @@ SRC_URI = "git://github.com/${BPN}-ocr/${BPN}.git;branch=main;protocol=https;tag
            file://CVE-2026-73066.patch \
            file://CVE-2026-73067-1.patch \
            file://CVE-2026-73067-2.patch \
+           file://CVE-2026-88052.patch \
 "
 
 
