CVE-2026-71513 Overview
CVE-2026-71513 is a remote code execution vulnerability in the Natural Language Toolkit (NLTK) affecting versions before 3.10.3. The flaw resides in AllowlistUnpickler, which validates only the pickle module string and not the global name. Attackers can resolve dotted names through attribute traversal to reach callables outside the allowlisted namespace. A crafted transition-parser model executes arbitrary commands when TransitionParser.parse loads the model through allowlisted_pickle_load. The vulnerability is classified as insecure deserialization [CWE-502].
Critical Impact
Attackers can achieve arbitrary command execution on any host that loads an untrusted NLTK transition-parser model, leading to full application compromise.
Affected Products
- NLTK versions prior to 3.10.3
- Python applications invoking TransitionParser.parse on untrusted models
- Downstream pipelines using allowlisted_pickle_load for scikit-learn or Punkt models
Discovery Timeline
- 2026-08-22 - CVE-2026-71513 published to NVD
- 2026-08-27 - Last updated in NVD database
Technical Details for CVE-2026-71513
Vulnerability Analysis
NLTK's AllowlistUnpickler was designed to restrict which classes and functions a pickle stream can reference during deserialization. The guard checked the module string against an allowlist such as ("numpy", "scipy", "sklearn") or ("nltk.tokenize.punkt", "nltk.tokenize"), but it did not validate the global name itself. Python's pickle GLOBAL and STACK_GLOBAL opcodes accept dotted names, and the unpickler resolved them through attribute traversal. An attacker can therefore reference numpy.f2py.crackfortran.myeval (an eval sink under the permitted numpy namespace) or a chained sklearn.os.system, escaping the allowlist without leaving it on paper. The malicious payload triggers on TransitionParser.parse, which calls allowlisted_pickle_load on the attacker-supplied model file.
Root Cause
The root cause is namespace-prefix allowlisting combined with unrestricted attribute traversal on globals. The prior allowlists permitted entire modules and their submodules, exposing every attribute, re-export, and dunder within those namespaces to pickle resolution.
Attack Vector
Exploitation requires a victim to load an attacker-controlled transition-parser or Punkt model file. Models are commonly shared through model registries, git repositories, or downloaded pretrained artifacts, making the network-borne, user-interaction-required delivery path realistic for machine-learning pipelines.
# Patch: nltk/parse/transitionparser.py
# Replaces namespace-prefix allowlist with an exact (module, qualname) allowlist.
_MODEL_ALLOWED_MODULES = ("numpy", "scipy", "sklearn")
_MODEL_ALLOWED_GLOBALS = (
("collections", "defaultdict"),
("collections", "OrderedDict"),
("builtins", "int"),
("builtins", "float"),
)
Source: NLTK security commit c3e3711
# Patch: nltk/tokenize/punkt.py
# Exact (module, qualname) allowlist -- no namespace prefix.
_PUNKT_ALLOWED_GLOBALS = (
("nltk.tokenize.punkt", "PunktSentenceTokenizer"),
("nltk.tokenize.punkt", "PunktParameters"),
("nltk.tokenize.punkt", "PunktLanguageVars"),
("nltk.tokenize.punkt", "PunktToken"),
("nltk.tokenize.punkt", "PunktTrainer"),
("nltk.tokenize.punkt", "PunktBaseClass"),
("nltk.tokenize.punkt", "PunktTokenizer"),
("nltk.probability", "FreqDist"),
("collections", "defaultdict"),
("builtins", "int"),
)
Source: NLTK security commit c3e3711
Detection Methods for CVE-2026-71513
Indicators of Compromise
- Unexpected child processes spawned by Python interpreters running NLTK, especially shells, os.system, or subprocess invocations.
- Model files loaded from untrusted paths or downloaded shortly before an NLTK parse operation.
- Pickle streams containing GLOBAL or STACK_GLOBAL opcodes referencing dotted names such as numpy.f2py.crackfortran.myeval or sklearn.os.system.
Detection Strategies
- Inventory Python environments and flag installations of nltk at versions below 3.10.3.
- Statically inspect pickle files with tools like pickletools to identify dotted-name globals outside expected classes.
- Correlate NLTK usage with process-execution telemetry to identify anomalous child processes originating from ML worker services.
Monitoring Recommendations
- Enable command-line and process-lineage logging on hosts running NLP or ML pipelines.
- Monitor file writes and network egress from Python worker processes that load third-party model artifacts.
- Alert on outbound connections initiated immediately after TransitionParser.parse or Punkt tokenizer loading.
How to Mitigate CVE-2026-71513
Immediate Actions Required
- Upgrade NLTK to version 3.10.3 or later across all environments, including CI runners and containerized ML services.
- Audit stored transition-parser and Punkt model files, discarding any acquired from untrusted or unverified sources.
- Restrict permissions on directories that hold pickled model artifacts to prevent tampering.
Patch Information
The fix is delivered in NLTK 3.10.3 via commit c3e3711. The patch replaces namespace-prefix allowlists with exact (module, qualname) tuples in both nltk/parse/transitionparser.py and nltk/tokenize/punkt.py, closing dotted-name attribute traversal. Additional details are available in the VulnCheck advisory.
Workarounds
- Only load NLTK models that were produced in-house or fetched from cryptographically verified sources.
- Run NLTK model loading in sandboxed processes with no network egress and minimal filesystem privileges.
- Replace pickled models with safer serialization formats such as JSON or ONNX where feasible.
# Upgrade NLTK to the patched release
pip install --upgrade "nltk>=3.10.3"
# Verify the installed version
python -c "import nltk; print(nltk.__version__)"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

