---
id: "CVE-2026-62388"
kind: "vulnerability"
aliases: ["CVE-2026-62388", "GHSA-p3m8-78j2-g5p3"]
title: "NLTK: Default ENFORCE=False Disables All pathsec Security Controls"
severity: "high"
cvss: 8.7
epss: 0.00512
exploited: false
status: "open"
category: "package"
products: [{"name": "nltk", "fixed": ["3.10.0"], "affected": "<= 3.9.4", "ecosystem": "pypi"}, {"name": "nltk", "fixed": ["3.10.0"], "affected": "< 3.10.0", "ecosystem": "vendor"}]
ecosystems: ["pypi", "vendor"]
tags: ["cwe-1188", "nltk", "package", "pypi", "python", "self-hosted"]
not_affected_if: ["enforce-env-set", "nltk-3.10.0-or-newer"]
published_at: "2026-08-22T15:16:18+00:00"
first_seen_at: "2026-10-27T08:02:10+00:00"
updated_at: "2026-10-27T08:31:47+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-p3m8-78j2-g5p3", "first_seen_at": "2026-10-27T08:02:10+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-62388", "first_seen_at": "2026-10-27T08:31:47+00:00"}]
---

# NLTK: Default ENFORCE=False Disables All pathsec Security Controls

NLTK's pathsec module defaults to warning-only mode, so its eight security checks log a warning instead of blocking violations. An attacker who can supply a path, URL or pickle source can read local files, reach internal URLs such as cloud metadata, or load unsafe pickles, and the earlier fixes for CVE-2024-39705 and CVE-2026-0846 do not block by default.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- pypi:nltk affected <= 3.9.4 fixed 3.10.0
- vendor:nltk affected < 3.10.0 fixed 3.10.0

## How to check

- Run `pip show nltk` and confirm the version is `3.9.4` or lower.
- Run `python -c "import nltk.pathsec as p; print(p.ENFORCE)"` and check for `False`.
- Check that the environment variable `NLTK_PATHSEC_ENFORCE` is not set to `1`, `true` or `yes`.

## Fix

- Upgrade `nltk` to `3.10.0`.
- Until upgraded, set `NLTK_PATHSEC_ENFORCE=1` in the environment that runs NLTK.

## Timeline

- 2026-10-27T08:02:10+00:00 ghsa https://github.com/advisories/GHSA-p3m8-78j2-g5p3
- 2026-10-27T08:31:47+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-62388

## From the sources

NLTK's pathsec.py security module defaults to ENFORCE=False (line 24), which means all 8 security validation functions only emit RuntimeWarning instead of raising exceptions when violations are detected.

The pathsec module was introduced as the fix for CVE-2024-39705 (arbitrary code execution via pickle) and CVE-2026-0846 (path traversal). However, with ENFORCE=False as the default:

1. pathsec.open('/etc/passwd') succeeds (reads the file, emits warning)
2. pathsec.validate_network_url('http://169.254.169.254/...') succeeds (warning only)
3. pickle.loads() via nltk.data.load() proceeds despite unsafe source (warning only)

Every security gate follows the same pattern:
```python
ENFORCE = os.environ.get('NLTK_PATHSEC_ENFORCE', '').lower() in ('1', 'true', 'yes')

def validate_something(path):
    if is_violation(path):
        if ENFORCE:
            raise SecurityError('...')  # Only raised when env var is set
        else:
            warnings.warn('...', RuntimeWarning)  # Default: warning only
    # Execution continues regardless
```

This means the security remediations for CVE-2024-39705 and CVE-2026-0846 are effectively disabled by default. Any user who installed NLTK 3.9.x expecting the security fixes to be active is still vulnerable unless they manually set NLTK_PATHSEC_ENFORCE=1.

PoC:
```python
import nltk.pathsec
import warnings

# Show that ENFORCE is False by default
print(f'ENFORCE = {nltk.pathsec.ENFORCE}')  # False

# Attempt to read /etc/passwd through pathsec -- should be blocked
with warnings.catch_warnings(record=True) as w:
    warnings.simplefilter('always')
    result = nltk.pathsec.open('/etc/passwd', 'r')
    print(f'File opened: {result.name}')  # /etc/passwd
    print(f'Warning emitted: {w[0].message}')  # RuntimeWarning (not an exception)
    # Attack succeeds -- file is readable
```

The correct default is fail-secure: ENFORCE should be True unless explicitly disabled. The current default makes the security module opt-in rather than opt-out, defeating its purpose.

Suggested fix: Change default to ENFORCE=True. Users who need backwards compatibility can set NLTK_PATHSEC_ENFORCE=0 to explicitly disable.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
