{"id":"CVE-2026-62388","kind":"vulnerability","aliases":["CVE-2026-62388","GHSA-p3m8-78j2-g5p3"],"related":[],"title":"NLTK: Default ENFORCE=False Disables All pathsec Security Controls","description":"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.\n\nThe 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:\n\n1. pathsec.open('/etc/passwd') succeeds (reads the file, emits warning)\n2. pathsec.validate_network_url('http://169.254.169.254/...') succeeds (warning only)\n3. pickle.loads() via nltk.data.load() proceeds despite unsafe source (warning only)\n\nEvery security gate follows the same pattern:\n```python\nENFORCE = os.environ.get('NLTK_PATHSEC_ENFORCE', '').lower() in ('1', 'true', 'yes')\n\ndef validate_something(path):\n    if is_violation(path):\n        if ENFORCE:\n            raise SecurityError('...')  # Only raised when env var is set\n        else:\n            warnings.warn('...', RuntimeWarning)  # Default: warning only\n    # Execution continues regardless\n```\n\nThis 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.\n\nPoC:\n```python\nimport nltk.pathsec\nimport warnings\n\n# Show that ENFORCE is False by default\nprint(f'ENFORCE = {nltk.pathsec.ENFORCE}')  # False\n\n# Attempt to read /etc/passwd through pathsec -- should be blocked\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter('always')\n    result = nltk.pathsec.open('/etc/passwd', 'r')\n    print(f'File opened: {result.name}')  # /etc/passwd\n    print(f'Warning emitted: {w[0].message}')  # RuntimeWarning (not an exception)\n    # Attack succeeds -- file is readable\n```\n\nThe 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.\n\nSuggested fix: Change default to ENFORCE=True. Users who need backwards compatibility can set NLTK_PATHSEC_ENFORCE=0 to explicitly disable.","summary":"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.","severity":"high","cvss":8.7,"epss":0.00512,"exploited":false,"exploited_at":null,"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"],"how_to_check":"- Run `pip show nltk` and confirm the version is `3.9.4` or lower.\n- Run `python -c \"import nltk.pathsec as p; print(p.ENFORCE)\"` and check for `False`.\n- Check that the environment variable `NLTK_PATHSEC_ENFORCE` is not set to `1`, `true` or `yes`.","fix":"- Upgrade `nltk` to `3.10.0`.\n- Until upgraded, set `NLTK_PATHSEC_ENFORCE=1` in the environment that runs NLTK.","status":"open","published_at":"2026-08-22T15:16:18+00:00","first_seen_at":"2026-10-27T08:02:10+00:00","triaged_at":"2026-10-27T08:03:27+00:00","updated_at":"2026-10-27T08:31:47+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-27T08:03:27Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade `nltk` to `3.10.0`.\n- Until upgraded, set `NLTK_PATHSEC_ENFORCE=1` in the environment that runs NLTK.","reach":"unknown","title":"NLTK: default setting turns off all path and URL security checks","impact":"high","summary":"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.","category":"package","nicknames":[],"who_cares":["python","nltk","pypi","self-hosted"],"confidence":0.8,"needs_auth":"unknown","worst_case":"Attacker reads local files or loads unsafe pickles despite security checks.","analyst_note":"","how_to_check":"- Run `pip show nltk` and confirm the version is `3.9.4` or lower.\n- Run `python -c \"import nltk.pathsec as p; print(p.ENFORCE)\"` and check for `False`.\n- Check that the environment variable `NLTK_PATHSEC_ENFORCE` is not set to `1`, `true` or `yes`.","needs_analyst":false,"not_affected_if":["nltk-3.10.0-or-newer","enforce-env-set"],"who_is_affected":"Any application that installs NLTK 3.9.4 or lower and passes it paths, URLs or untrusted pickled data through nltk.data or pathsec functions is exposed. Services that only load NLTK's bundled data from trusted local paths are at much lower risk.","user_interaction":"no","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000731,"input_tokens":4130,"output_tokens":637,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-0846':91B,146C,241C '-1188':24B '-2024':86B,136C,236C '-2026':11A,19A,90B,145C,240C '-39705':87B,137C,237C '-62388':12A,20A '/etc/passwd':158C,293C,310C,317C '0':323C,383C '1':156C,198C,271C '169.254.169.254':169C '2':165C '24':107C '3':173C '3.9':252C '78j2':16A '8':111C 'activ':260C 'alway':307C 'arbitrari':138C 'attack':55B,329C 'attempt':290C 'backward':376C 'block':52B,94B,298C 'chang':368C 'check':46B 'cloud':74B 'code':139C 'compat':377C 'continu':227C 'control':9A 'correct':335C 'current':349C 'cve':10A,18A,85B,89B,135C,144C,235C,239C 'cwe':23B 'def':201C 'default':2A,36B,96B,102C,155C,223C,246C,284C,336C,350C,369C 'defeat':363C 'despit':178C 'detect':125C 'disabl':5A,244C,347C,386C 'earlier':82B 'effect':243C 'eight':44B 'els':220C 'emit':116C,163C,321C 'enforc':3A,104C,151C,191C,195C,210C,270C,280C,287C,341C,371C,382C 'env':216C 'everi':183C 'except':121C,328C 'execut':140C,226C 'expect':254C 'explicit':346C,385C 'f':286C,313C,319C 'fail':339C 'fail-secur':338C 'fals':4A,105C,152C,282C,289C 'file':68B,162C,314C,331C 'fix':83B,133C,257C,367C 'follow':186C 'function':114C 'g5p3':17A 'gate':185C 'ghsa':14A 'ghsa-p3m8-78j2-g5p3':13A 'host':31B 'howev':149C 'import':274C,276C 'instal':250C 'instead':50B,118C 'intern':70B 'introduc':130C 'line':106C 'load':77B 'local':67B 'log':47B 'lower':196C 'make':351C 'manual':266C 'mean':109C,230C 'messag':324C 'metadata':75B 'mode':41B 'modul':35B,101C,128C,354C 'need':375C 'network':167C 'nltk':1A,21A,22A,25B,32B,97C,193C,251C,268C,380C 'nltk.data.load':176C 'nltk.pathsec':275C 'nltk.pathsec.enforce':288C 'nltk.pathsec.open':309C 'open':315C 'opt':356C,361C 'opt-in':355C 'opt-out':360C 'os.environ.get':192C 'p3m8':15A 'packag':26B 'path':60B,147C,204C,208C 'pathsec':7A,34B,127C,194C,269C,295C,381C 'pathsec.open':157C 'pathsec.py':99C 'pathsec.validate':166C 'pattern':189C 'pickl':63B,79B,142C 'pickle.loads':174C 'poc':272C 'print':285C,312C,318C 'proceed':177C 'purpos':365C 'pypi':27B 'python':28B,190C,273C 'r':311C 'rais':120C,211C,214C 'rather':358C 'reach':69B 'read':66B,160C,292C 'readabl':333C 'record':302C 'regardless':228C 'remedi':233C 'result':308C 'result.name':316C 'runtimewarn':117C,222C,325C 'secur':8A,45B,100C,112C,184C,232C,256C,340C,353C 'securityerror':212C 'self':30B 'self-host':29B 'set':219C,267C,379C 'show':278C 'someth':203C 'sourc':64B,180C 'still':262C 'succeed':159C,170C,330C 'suggest':366C 'suppli':58B 'travers':148C 'true':199C,303C,344C,372C 'unless':264C,345C 'unsaf':78B,179C 'url':61B,71B,168C 'user':248C,373C 'valid':113C,202C 'var':217C 'via':141C,175C 'violat':53B,123C,207C 'vulner':263C 'w':305C,322C 'warn':39B,49B,164C,171C,181C,224C,277C,301C,320C 'warning-on':38B 'warnings.catch':300C 'warnings.simplefilter':306C 'warnings.warn':221C 'x':253C 'yes':200C","nicknames":[],"mitigations":[],"who_affected":"Any application that installs NLTK 3.9.4 or lower and passes it paths, URLs or untrusted pickled data through nltk.data or pathsec functions is exposed. Services that only load NLTK's bundled data from trusted local paths are at much lower risk.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-08-22T15:16:18+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"disclosure@vulncheck.com","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-p3m8-78j2-g5p3","url":"https://github.com/advisories/GHSA-p3m8-78j2-g5p3","severity":"high","published_at":"2026-09-02T15:40:33+00:00","modified_at":"2026-10-27T07:57:48+00:00","first_seen_at":"2026-10-27T08:02:10+00:00","fetched_at":"2026-10-27T08:02:10+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-62388","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-62388","severity":null,"published_at":"2026-08-22T15:16:18+00:00","modified_at":"2026-10-14T13:10:00+00:00","first_seen_at":"2026-10-27T08:31:47+00:00","fetched_at":"2026-10-27T08:31:47+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}