CVE-2026-78680High· 7.8▾ TwilightNLTK: Uncontrolled search path when invoking the Graphviz 'dot' binary
▾ Twilight zone — High severity, or a signal on a lesser flaw
impact 42.9 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Exploit-prediction probability, daily snapshots since Sep 1.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via OSV
0.1%
Last analysed / modified upstream
Two NLTK sites executed the Graphviz dot program by bare name, so process creation resolved it via the search path — and on Windows via the current working directory — rather than a validated absolute location. An attacker who can place a file named dot where resolution looks (the CWD on Windows, or a writable/relative entry such as . on PATH) has their binary executed in place of Graphviz (arbitrary code execution).
Affected (<= 3.10.2):
nltk.parse.dependencygraph.dot2img — called find_binary("dot") but discarded the returned validated path and then ran the bare name ["dot", ...], so the validation had no effect.nltk.translate.api.AlignedSent._repr_svg_ — ran the bare name with no validation at all (IPython SVG rendering).This is the same class already fixed for the senna, weka, boxer, malt, repp and hunpos wrappers. nltk.internals.find_binary refuses a CWD-relative match for a bare tool name and returns only a trusted absolute path; the fix runs that path in both sites.
Captured output, not illustrative. A ./dot that writes a PWNED marker, planted in the CWD with . prepended to PATH.
The vulnerable behaviour (old bare-name exec):
Control (OLD behavior) — bare ['dot'] in this dir with '.' on PATH:
bare ['dot'] executed planted binary = True
The patched functions refuse it:
FIXED code, with ./dot planted and '.' on PATH:
dependencygraph.dot2img : Exception "Cannot find the dot binary..." | planted-binary-executed=False safe
AlignedSent._repr_svg_ : Exception "Cannot find the dot binary..." | planted-binary-executed=False safe
And find_binary itself was attacked directly (the fix trusts nothing else):
Attack 1: ./dot in CWD, no dot on PATH -> LookupError (refused) safe
Attack 2: ./dot/dot (dir 'dot' holding 'dot') -> LookupError (refused) safe
Attack 3: '.' on PATH + ./dot -> LookupError (refused) safe
Attack 4: attacker-writable ABSOLUTE dir on PATH -> returned /…/evilbin/dot (absolute)
Attack 4 is out of scope: trusting an absolute directory that is already on PATH is the operating system's own trust model — an attacker who can write to a PATH directory owns the account regardless of NLTK. find_binary defends specifically against the CWD/relative injection that bare-name exec is vulnerable to (attacks 1–3), which is exactly what this fix inherits.
Environment: python 3.13.7. dot is not required to reproduce — the planted binary is the payload.
nltk < 3.10.3Upgrade to a patched release:
nltk 3.10.3Connected by shared product, vendor, weakness, or advisory.
CVE-2026-12876MediumNLTK: Uncontrolled resource consumption in RecursiveDescentParser via ambiguous or left-recursive grammars
CVE-2026-81723Low· 3.7NLTK: Quadratic CPU Exhaustion in `XMLCorpusView._read_xml_fragment()`
CVE-2026-80206HighNLTK: ReDoS in nltk.tgrep via unvalidated user-supplied regular expressions
CVE-2026-78681HighNLTK: Entity-expansion DoS (billion laughs) via remaining raw ElementTree parses
CVE-2026-79676HighNLTK: Corpus readers follow symlinks outside trusted roots despite pathsec enforcement
CVE-2026-79657CriticalNLTK: Allowlisted pickle loaders still permit code execution in current source