CVE-2026-88051
High · 7.8CVSS
7.8
EPSS
0.2%
Published
Sep 10, 2026
CISA due date
—
Cloudanix analysis
If this OCR software is given a tampered language-model file, it can crash or be taken over, and there is not yet an official fixed version.
- 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
Tesseract 5.5.3 and earlier contain a heap out-of-bounds write in the callback form of GenericVector::read when parsing a .traineddata model. The TESSDATA_INTTEMP component can specify a small reserved count and a much larger size_used_ with no cap or invariant check; reserve() allocates the smaller backing array while the read loop writes size_used_ FontInfo records via fontinfo_table_.read in intproto.cpp. The result is heap corruption, process crash, or potentially attacker-controlled heap overwrite in the OCR process. Attack vector is local (loading a model file); confidentiality, integrity, and availability of the Tesseract process can all be lost. No patched upstream release is available.
Why it matters to the business
Any product or pipeline that loads Tesseract language or classifier models from untrusted or weakly controlled sources (user-supplied models, shared tessdata directories, document-ingestion workers, or third-party model packs) can be crashed or, in a worst case, have the OCR process compromised. Impact is downtime of OCR/document workflows, integrity loss of extracted text, and possible follow-on compromise of the host running Tesseract. An exploit is reported available, the issue has been public for weeks, and there is still no vendor-fixed version, so operational risk remains elevated until models are strictly controlled or the engine is isolated. Downstream OCR, IDP, and scanning products that embed tesseract-ocr are in the same exposure class.
How an attack unfolds
An attacker supplies a malicious Tesseract .traineddata model rather than attacking the network service directly. The file is placed where an application will load it—shared tessdata, a model upload, a document-processing worker, or a local CLI invocation. When Tesseract initializes classification and reads the INTTEMP table, mismatched vector length fields cause a heap write past the allocated FontInfo array. That yields a crash for denial of service or heap corruption that may be leveraged for code execution in the Tesseract process context. Because loading requires local file access (or an app that loads attacker-controlled models), the typical victim is an OCR pipeline or desktop/tooling path that trusts model files. Public exploit maturity is reported as available, so opportunistic use against unpatched embeddings should be assumed.
How to fix it
No official fixed Tesseract release is available; do not wait on a version bump as the sole control. Immediately stop loading .traineddata files from untrusted users, public downloads, or writable shared directories. Pin and inventory tessdata to a signed, internally approved set; enforce restrictive file permissions so runtime users cannot replace models. Run Tesseract in a tightly sandboxed worker (seccomp/AppArmor/containers, no extra privileges, minimal filesystem) so a crash or heap smash cannot reach the rest of the host. Prefer compiling or deploying only after an upstream patch exists; track tesseract-ocr releases and rebuild embeddings as soon as a fix ships. If you maintain a fork, add an invariant that reserved >= size_used_ (and a sane upper bound) before allocate-and-fill in GenericVector::read and reject INTTEMP tables that fail the check. Disable unused classifier/model components where the product does not need them.
How to confirm the fix worked
Inventory every binary, container, and language binding that ships or dlopens tesseract; confirm engine version is 5.5.3 or earlier (vulnerable) versus a later build that includes a length-check fix once published. Locate all tessdata/.traineddata paths and verify they are not world-writable and not populated from user upload. In a non-production harness, confirm the application refuses or fails closed on truncated/malformed models without writing past heap buffers—do not use public exploit files on production. After sandboxing, verify the OCR worker cannot write outside its model/cache directories and that crashes do not restart into a privileged context. Re-scan images and SBOMs when an upstream fixed version appears and require that exact engine version in CI.
Typical attack path
- Obtain or plant a crafted Tesseract .traineddata model intended to be loaded by a vulnerable engine (5.5.3 or earlier).
- Deliver the model into a trusted tessdata path, upload/API that accepts custom models, or a local working directory used by an OCR job.
- Trigger model load through normal OCR/classification (CLI, library Init, or an embedding that calls font/classifier table read).
- Heap out-of-bounds write occurs during GenericVector read of FontInfo records.
- Outcome is process crash (DoS) or heap corruption that may allow further compromise of the OCR process and, depending on sandboxing, the host.
How to detect it
This is a local model-parse bug, so look for evidence that a non-standard .traineddata was loaded and that the Tesseract process then crashed or behaved abnormally—not for a remote packet signature. Review tessdata directories and model-upload storage for files added or replaced around OCR jobs; compare hashes to your approved model set. Inspect OCR worker logs, syslog/journal, and container runtime logs for tesseract or embedding-library crashes, abort/SIGSEGV/SIGABRT, and heap-allocator fatal errors during Init or classifier load. On hosts with core dumps or crash reporters (apport, Windows Error Reporting, Breakpad/Crashpad), search for tesseract, libtesseract, or process names of apps that embed OCR, with crash stacks in genericvector/intproto/FontInfo read paths. Audit auditd/file-integrity (AIDE/osquery) events on tessdata paths. Network IOCs are generally absent unless models were downloaded; in that case pair file-create events with the download source. There are no named KEV/ransomware campaigns in the provided data; hunt on artifacts rather than actor-specific C2.
- *.traineddata
- tessdata/
- TESSDATA_INTTEMP
- tesseract
- libtesseract.so
- libtesseract.dylib
- tesseract.exe
- fontinfo_table_
- intproto.cpp
- GenericVector
- SIGSEGV
- SIGABRT
- malloc(): corrupted
- double free or corruption
- std::bad_alloc
What your security team should do
- Treat untrusted .traineddata as equivalent to untrusted native code until a patched engine is deployed; block model uploads and lock tessdata to a signed allowlist.
- Sandbox or containerize every Tesseract worker now; assume crash and heap corruption are achievable because an exploit is reported available and no vendor fix exists.
- Inventory tesseract-ocr 5.5.3 and earlier across products, CLI hosts, and IDP pipelines; ticket owners for isolation and model-path hardening within days, not a normal patch cycle.
- Subscribe to upstream Tesseract security/release notes and fast-follow the first fixed version into all embeddings.
- Add detection for unexpected traineddata files and Tesseract crash/coredump spikes; hunt historical model-directory changes.
- If you ship Tesseract, document that custom models are unsupported until patched and ship only vetted tessdata.
The record
Tesseract is an open source OCR engine. In version 5.5.3 and earlier, the callback form of GenericVector::read in src/ccutil/genericvector.h reads the independent int32 fields reserved and size_used_ from a .traineddata model without a cap or an invariant check. reserve(reserved) allocates the backing array, but the callback loop writes size_used_ elements. A crafted TESSDATA_INTTEMP component with version_id 4 or later can therefore set reserved to a small value and size_used_ to a large value when fontinfo_table_.read(fp, read_info) is called from src/classify/intproto.cpp, causing a heap out-of-bounds write of FontInfo structures, heap corruption, a crash, or potentially controlled corruption. No fixed release is available as of this review.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|
Related vulnerabilities
- CVE-2026-111497 A buffer overflow vulnerability in the Brotli decoder (c/dec/decode.c) in Google Brotli… CWE-787
- CVE-2026-112397 Pillow is a Python imaging library. CWE-787
- CVE-2026-112059 libLAS through 1.8.1 contains a heap out-of-bounds write vulnerability in the point… CWE-787
- CVE-2026-89088 A flaw was found in parted. CWE-787
- CVE-2026-89085 A flaw was found in parted. CWE-787
- CVE-2026-85746 MariaDB server is a community developed fork of MySQL server. CWE-787
- CVE-2026-107815 MariaDB server is a community developed fork of MySQL server. CWE-787
- CVE-2026-56851 The Nickname profile can panic with an out-of-bounds slice error when transforming… CWE-787