Cloudanix VulnDB

CVE-2026-88050

Medium · 5.5

CVSS

5.5

EPSS

0.1%

Published

Sep 10, 2026

CISA due date

—

Cloudanix analysis

Monitor only SSVC: Track

Software that reads text from images can be forced to crash if it loads a tampered language-data file, which can halt document processing until the program is restarted.

Exploitation
Other
Attacker needs
Local User
Complexity
Low
Impact
Denial Of Service
Component
Library
Class
Memory Corruption
Remediation
No Fix Yet
Effort
Other
Patch risk
Low

What it actually does

Tesseract OCR 5.5.3 and earlier deserializes a recoder component from a .traineddata file in RecodedCharID::DeSerialize without rejecting negative code_ values. UnicharCompress::ComputeCodeRange can then set a zero code_range_, after which SetupDecoder indexes a size-zero is_valid_start_ vector with the negative code. The wrapped index produces an out-of-bounds bit write that reliably crashes the default LSTM engine or fails an allocation. Impact is availability-only: process abort, not confidentiality or integrity compromise.

Why it matters to the business

OCR pipelines that load language models can be taken down by a single malformed .traineddata file, interrupting document ingestion, invoice capture, ID scanning, and similar workflows until the worker is restarted. CVSS 5.5 reflects local denial of service, not data theft. The issue is not in CISA KEV, is not associated with ransomware, and has no known in-the-wild exploit, but 27 days after publication there is still no patched release, so any product embedding Tesseract 5.5.3 or earlier remains exposed to crash-based disruption.

How an attack unfolds

An attacker who can cause Tesseract to load an untrusted .traineddata language pack—by writing a file onto a local tessdata path, substituting a model in a shared volume, or shipping a malicious language pack into an OCR job—triggers recoder deserialization. Negative code values that pass the length check collapse the decoder table to zero size; SetupDecoder then performs a wild-address write and the LSTM engine aborts. The published vector is local (AV:L), needs no privileges or user click beyond loading the model, and yields a crash rather than code execution. No named threat actors or exploit kits are associated with this CVE, and exploit maturity is none.

How to fix it

No fixed Tesseract release is available as of this review; there is no version to upgrade to yet. Treat all .traineddata files as trusted input only: load models exclusively from official tessdata sources, pin and verify checksums or signatures before use, and block runtime replacement of language packs. Run tesseract (and libraries that embed it) in a tightly sandboxed worker with a supervisor that restarts on crash so a single abort cannot take down adjacent services. Disable or avoid loading custom recoder/traineddata components from user-supplied uploads. Watch the tesseract-ocr project for a release newer than 5.5.3 and upgrade immediately when one ships.

How to confirm the fix worked

Inventory every Tesseract binary and embedded copy (tesseract --version, package manager, container base images, and linked libtesseract). Versions 5.5.3 and earlier are affected. List all .traineddata files and TESSDATA_PREFIX locations and confirm hashes match official tessdata artifacts. Verify application code and job configs cannot accept attacker-controlled language packs. After sandboxing or model pinning, confirm untrusted traineddata cannot be loaded and that OCR workers recover cleanly from a crash. When a patched release appears, upgrade and re-run standard OCR smoke tests against known-good models.

Typical attack path

  1. Place or substitute a .traineddata file on a path Tesseract will load (local tessdata directory, TESSDATA_PREFIX, or an OCR job’s language-pack input).
  2. Cause the OCR process to initialize the default LSTM engine so UnicharCompress deserializes the recoder component.
  3. Tesseract computes a zero code range and performs an out-of-bounds write during SetupDecoder.
  4. The OCR worker crashes or fails allocation, denying service until it is restarted.

How to detect it

Hunt for crashes of tesseract or processes linked to libtesseract, especially at LSTM/engine init when a .traineddata file is loaded. Review application and syslog/journald records around OCR jobs, core dumps and sanitizer/crash reports whose stacks mention RecodedCharID::DeSerialize, UnicharCompress::ComputeCodeRange, or SetupDecoder, and file-integrity or audit logs for unexpected creation or replacement of *.traineddata under tessdata directories or TESSDATA_PREFIX. Because exploit maturity is none and no threat actors are tied to this CVE, treat a matching crash plus a non-official traineddata file as suspicious but not proof of a campaign; preserve the model file and coredump for comparison to known-good tessdata hashes.

  • tesseract
  • libtesseract
  • *.traineddata
  • TESSDATA_PREFIX
  • tessdata/
  • RecodedCharID::DeSerialize
  • UnicharCompress::ComputeCodeRange
  • UnicharCompress::SetupDecoder
  • src/ccutil/unicharcompress
  • is_valid_start_

What your security team should do

  • Treat untrusted .traineddata / language-pack input as a crash primitive and block it at the application and file-integrity layer until a patch exists.
  • Inventory Tesseract 5.5.3 and earlier across hosts, containers, and downstream OCR products; track them for an emergency upgrade when a fix is published.
  • Sandbox OCR workers (seccomp/AppArmor/containers, non-root, no shared writable tessdata) and add crash-restart so denial of service stays local to the worker.
  • Alert on Tesseract aborts, coredumps in unicharcompress/SetupDecoder, and unexpected writes under tessdata or TESSDATA_PREFIX.
  • Do not wait on KEV or ransomware tagging—this is a reliability risk to document pipelines, not a mass-exploitation emergency, but the missing patch means compensating controls are the only fix today.

The record

Tesseract is an open source OCR engine. In version 5.5.3 and earlier, RecodedCharID::DeSerialize in src/ccutil/unicharcompress.h validates length_ but accepts negative code_ values from a crafted .traineddata recoder component. UnicharCompress::ComputeCodeRange in src/ccutil/unicharcompress.cpp can consequently produce code_range_ equal to zero, after which SetupDecoder indexes is_valid_start_ with the negative code on a size-zero vector. The resulting out-of-bounds bit write uses a large wrapped index and reliably causes a wild-address crash or allocation failure on the default LSTM engine. No fixed release is available as of this review.

Affected packages

Ecosystem Package Introduced Fixed

Related vulnerabilities