# Incomplete Fix for CVE-2024-39705 — Multiple Unsafe Pickle Loading Paths Remain in NLTK in [nltk/nltk](https://github.com/nltk/nltk)

Reported on Apr 11th 2026

---

## Description

The fix for CVE-2024-39705 (unsafe pickle deserialization in NLTK data loading) was incomplete. While `nltk/data.py` was hardened to use `RestrictedUnpickler` (which blocks all class instantiation), multiple other code paths still use `pickle_load()` from `nltk.picklesec` with the default `restricted=False` parameter.

When `restricted=False` (the default), `pickle_load()` uses `WarningUnpickler` which **only emits a RuntimeWarning but does NOT prevent code execution**. This is functionally equivalent to `pickle.load()` with a warning message.

## Affected Call Sites

| File | Line | Function |
| --- | --- | --- |
| `nltk/parse/transitionparser.py` | 557 | `TransitionParser.parse()` — loads model from user-supplied path |
| `nltk/app/chartparser_app.py` | 816 | Chart loading via GUI |
| `nltk/app/chartparser_app.py` | 2273 | ChartComparer |
| `nltk/tbl/demo.py` | 257, 329 | Tagger loading |

The most dangerous is `transitionparser.py:557` which loads a model file from a user-supplied path as part of the core parsing API.

## Steps to Reproduce

```python
import pickle, os

# Create malicious pickle file
class Exploit:
    def __reduce__(self):
        return (exec, ("print('RCE via NLTK pickle bypass!')",))

with open("evil_model.pickle", "wb") as f:
    pickle.dump(Exploit(), f)

# Load via NLTK TransitionParser (bypasses CVE-2024-39705 fix)
from nltk.parse.transitionparser import TransitionParser
tp = TransitionParser.__new__(TransitionParser)
tp._modelfile = "evil_model.pickle"

# This calls pickle_load with restricted=False (default)
# WarningUnpickler only warns but still executes the payload
from nltk.picklesec import pickle_load
result = pickle_load("evil_model.pickle")
# Output: RCE via NLTK pickle bypass!
```

The `WarningUnpickler` emits a warning but the malicious code still executes. Users who updated NLTK after CVE-2024-39705 believe they are protected, but these code paths were not patched.

## Impact

Remote Code Execution. An attacker who provides a malicious pickle file (e.g., a crafted transition parser model) can execute arbitrary Python code when a user loads it. The WarningUnpickler only emits a warning but does not block execution. This is an incomplete fix for CVE-2024-39705 — users who updated NLTK believe they are protected but these code paths remain vulnerable.

## References

- [https://cwe.mitre.org/data/definitions/502.html](https://cwe.mitre.org/data/definitions/502.html)

Severity

None (0)

Attack vector Network

Attack complexity Low

Privileges required None

User interaction None

Scope Unchanged

Confidentiality None

Integrity None

Availability None

Registry

Pypi

Affected Version

3.9.1

Status

Duplicate

Found by

[Wolfpack.Army](/content/users/skillwager/index.html) @skillwager
