HIGHCVSS v3.1 7.8Vulnerability

CVE-2026-115878

## TL;DR Loading an attacker-supplied lemma `.pt` runs arbitrary code as the loading user. Since 1.14.0 the lemmatizer stores `pos_dict` as a gzip-compressed pickle in the checkpoint's `dicts` field (a `bytes` value). `torch.load(weights_only=True)` treats `bytes` as a primitive and passes it through unexamined, so its allowlist never sees the inner stream. `Trainer.load` then feeds those bytes to an **unrestricted `pickle.loads`**: the only bare `pickle.loads` in the tree. Result: `weights_only=True` gives no protection here, and model loading executes code. Confirmed end-to-end against stanza 1.14.0 / PyTorch 2.13.0 / CPython 3.13.7: a crafted checkpoint whose payload `__reduce__` returns `(os.system, (cmd,))` ran the command at load time (marker file showed `uid=501(...)`, `executed_by=...`). A downstream user is vulnerable whenever they build a pipeline that loads a caller-supplied lemmatizer checkpoint. i.e. `stanza.Pipeline(lang=..., processors="tokenize,pos,lemma", lemma_model_path="<attacker-influenced .pt>")` (or any equivalent load of an untrusted/shared lemma model through a custom registry) - since that call routes straight into `Trainer.load` -> `_unpack_pos_dict` and executes the embedded pickle at construction time. ## The vulnerable path `stanza/models/lemma/trainer.py`: ```python # _pack_pos_dict (write side): pos_dict -> pickle -> gzip -> bytes, stored under checkpoint['dicts'] def _unpack_pos_dict(data): # line 54 buf = io.BytesIO(data) with gzip.GzipFile(fileobj=buf, mode="rb") as gz: raw = gz.read() return pickle.loads(raw) # <-- unrestricted default unpickler ``` ```python def load(self, filename, ...): # line 365 checkpoint = torch.load(filename, ..., weights_only=True) # outer allowlist; bytes pass through intact ... if dicts_version == _DICTS_VERSION_POS: # dicts_version == 2 (current format) self.pos_dict = _unpack_pos_dict(chec

Properties

Summary
Stanza: RCE via pickle deserialization in the lemmatizer
Severity
high
Nvd fetched at
2026-11-03T21:24:30.963596+00:00
Cvss score
7.8
Cvss severity
HIGH
Retrieved at
2026-11-03T21:26:50+00:00
Ghsa published
2026-11-03T20:29:16Z
Source url
https://github.com/advisories/GHSA-gh9r-c94j-cmp5
Ghsa updated
2026-11-03T20:29:16Z
Ghsa id
GHSA-gh9r-c94j-cmp5
Last source
GitHub Advisory Database
Score
7.8
Cvss version
3.1
Cve id
CVE-2026-115878
Cvss vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
First seen by Signal
2026-11-03T21:21:12+00:00
Is ghsa only
false
Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Published at
2026-11-03T21:17:02.377
Last modified
2026-11-03T21:17:02.377

Related Entities (4)

AFFECTS (1)

→[Software]pip/stanza

VULNERABLE_TO (1)

←[Software]pip/stanza

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-115878 (CVSS v3.1 7.8) — Ninja Signal Threat Intelligence | Ninja Signal