Cloudanix VulnDB

CVE-2026-88047

High · 7.8

CVSS

7.8

EPSS

0.1%

Published

Sep 10, 2026

CISA due date

—

Cloudanix analysis

Monitor only SSVC: Track

A common text-reading library can crash or be taken over if it opens a tampered language-data file, and there is not yet an official update to fix it.

Exploitation
Local Privilege
Attacker needs
Local User
Complexity
Low
Impact
Full Compromise
Component
Library
Class
Buffer Overflow
Remediation
No Fix Yet
Effort
Other
Patch risk
Low

What it actually does

A stack buffer overflow in Tesseract’s legacy classifier (Classify::ReadNormProtos in normmatch.cpp) occurs when a .traineddata file’s NORMPROTO section is parsed. An unbounded std::istream extraction writes a whitespace-delimited token into a fixed 61-byte stack buffer, so an oversized token can overwrite adjacent stack memory during TessBaseAPI::Init. Typical libstdc++ builds can suffer stack corruption, process crash, or control-flow hijack in the OCR process; Apple libc++ C++20 bounded-array overloads are incidentally not affected. Versions 5.5.3 and earlier are in scope.

Why it matters to the business

Document-processing, IDP, and accessibility services that embed Tesseract can be crashed or, in the worst case, fully compromised if they load a tampered language-data file. Impact is high for confidentiality, integrity, and availability of the OCR process, but exploitation requires the ability to supply or replace a .traineddata file (local/file-supply, not remote unauthenticated). No official patched release exists, so residual risk remains on 5.5.3 and earlier. The issue is not in CISA KEV, is not associated with ransomware, and has no reported in-the-wild use 27 days after publication—urgency is driven by the missing patch and the need to treat untrusted traineddata as untrusted code, not by active mass exploitation.

How an attack unfolds

An attacker who can place or substitute a Tesseract language-data file causes the application to initialize the legacy OCR engine with that file. During TessBaseAPI::Init, the NORMPROTO parser reads an oversized token into a too-small stack buffer, corrupting the stack. On affected libstdc++ runtimes the process may abort or, if control data is overwritten, execute attacker-chosen flow with the privileges of the OCR worker. Apple libc++ C++20 builds typically fail closed on this extraction. No public exploit, named threat actor, or ransomware campaign is associated with this CVE; exploit maturity is none.

How to fix it

No vendor-fixed version is available; do not expect an upgrade target yet. Stop loading .traineddata files from untrusted or user-influenced locations and allowlist only known-good, integrity-checked language packs. If the legacy classifier is not required, configure embeddings to use LSTM-only initialization so this NORMPROTO parse path is not exercised. Lock down tessdata directories and TESSDATA_PREFIX (root-owned, not world-writable). Run OCR in a least-privilege sandbox, not as a privileged service. For in-house builds, keep stack canaries, ASLR, and fortified headers enabled; Apple libc++ C++20 toolchains are incidentally protected. Watch the Tesseract project for a release newer than 5.5.3 and apply it as soon as it exists.

How to confirm the fix worked

Inventory hosts and images shipping tesseract-ocr / libtesseract 5.5.3 or earlier. Determine whether applications call TessBaseAPI::Init with the legacy engine and whether they load third-party or user-supplied .traineddata files. Verify tessdata paths are not writable by unprivileged users and that only hashed, vendor-or-internally-approved packs are present. After mitigations, confirm untrusted traineddata cannot be loaded (permissions and allowlists) and that LSTM-only mode is in use where legacy OCR is unnecessary. Re-check when a patched Tesseract release is published; Apple libc++ C++20 environments should confirm they actually use the bounded extraction overload.

Typical attack path

  1. Gain the ability to supply or replace a .traineddata language pack (writable tessdata directory, TESSDATA_PREFIX, malicious download, or an app that accepts custom models).
  2. Prepare a traineddata file whose NORMPROTO component contains an overly long whitespace-delimited token.
  3. Trigger TessBaseAPI::Init so the victim process loads that file with the legacy engine.
  4. Overflow occurs in Classify::ReadNormProtos, corrupting stack memory.
  5. Outcome is denial of service via crash, or—on vulnerable standard-library implementations—possible control-flow hijack in the OCR process.
  6. If execution is gained, operate with the privileges of the embedding application (often a document worker), not necessarily host-wide root.

How to detect it

No in-the-wild exploitation, KEV listing, or named actor activity is reported, so hunt for accidents and staging rather than a known campaign. Inspect crash dumps and core files from processes linked to libtesseract that fail during startup; stack frames naming Classify::ReadNormProtos, normmatch.cpp, or TessBaseAPI::Init are the strongest application-level signal. Review file create/modify events for *.traineddata under tessdata directories, TESSDATA_PREFIX, temp, and user-upload paths, and compare packs to known-good hashes. Alert when tesseract or an embedding app loads language data from an unexpected directory. Network IOCs are not applicable; this is a local file-parse flaw.

  • ReadNormProtos
  • Classify::ReadNormProtos
  • normmatch.cpp
  • TessBaseAPI::Init
  • NORMPROTO
  • *.traineddata
  • libtesseract
  • tesseract
  • TESSDATA_PREFIX

What your security team should do

  • Immediately treat .traineddata as executable-equivalent input: allowlist known-good packs and block user- or internet-supplied models.
  • Find every service embedding Tesseract 5.5.3 or earlier, prioritizing those that initialize the legacy engine or accept custom language data.
  • Sandbox OCR workers with least privilege and no write access to tessdata or unrelated secrets.
  • Disable the legacy engine when LSTM-only OCR meets the product need.
  • Harden tessdata and TESSDATA_PREFIX permissions; alert on unexpected traineddata drops.
  • Track Tesseract releases and patch the day a fix ships—there is no KEV deadline, but there is also no patch today.
  • Hunt for tesseract/libtesseract crashes during init; there is no evidence of exploitation yet, so unexplained crashes plus new traineddata files are the practical signal.

The record

Tesseract is an open source OCR engine. In version 5.5.3 and earlier, Classify::ReadNormProtos in src/classify/normmatch.cpp parses the NORMPROTO component of a .traineddata file and uses std::istream::operator>>(char*) to extract a whitespace-delimited token into a fixed 61-byte stack buffer without setting a stream width. The 100-byte line buffer can carry a token of up to 99 characters, so a token longer than 60 characters writes up to 39 attacker-controlled bytes past the buffer during TessBaseAPI::Init of the legacy engine, causing stack corruption, denial of service, and potentially control-flow hijacking on affected standard-library implementations. Builds using Apple's libc++ C++20 bounded array overload are incidentally protected, while typical libstdc++ builds remain affected. No fixed release is available as of this review.

Affected packages

Ecosystem Package Introduced Fixed

Related vulnerabilities