Sploitus

Exploit for CVE-2026-12243

githubexploit Β· 2026-08-29

Exploit Code

README196 lines
## https://sploitus.com/exploit?id=521582AC-2452-55F6-83CC-FA8F15B5F4FD
# CVE-2026-12243 β€” NLTK Path Traversal Lab

[![CVE](https://img.shields.io/badge/CVE-2026--12243-red)](https://nvd.nist.gov/vuln/detail/CVE-2026-12243)
[![NLTK](https://img.shields.io/badge/affected-NLTK%20%3C%203.10.0-orange)](https://github.com/advisories/GHSA-m42h-3232-vpv3)
[![Lab](https://img.shields.io/badge/scope-local--only-blue)](#safety-model)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)

A small, reproducible Docker lab that contrasts the percent-encoded path
traversal behavior in NLTK 3.9.4 with the corrected behavior in NLTK 3.10.0.

The vulnerable version validates the resource name before URL decoding. The
fixed payload `%2e%2e/%2e%2e/outside/lab-secret.txt` passes the check, is later
decoded to `../../outside/lab-secret.txt`, and escapes both the configured
NLTK data directory and the process working directory. The patched version
rejects the same input.

> [!CAUTION]
> This repository is for defensive education and authorized testing only. The
> lab uses a fixed synthetic secret inside an isolated container. Do not adapt
> it to access systems or data you do not own or have explicit permission to
> test.

## At a glance

| Container | NLTK version | Expected result |
| --- | ---: | --- |
| `vulnerable` | `3.9.4` | Reads the synthetic marker outside `/lab/nltk_data` |
| `patched` | `3.10.0` | Blocks the encoded traversal |

No corpus download, server, port, bind mount, or runtime internet connection
is used.

## Prerequisites

- Docker Engine or Docker Desktop
- Docker Compose v2 (`docker compose`)
- A POSIX shell for `run.sh`

## Usage

```bash
git clone https://github.com/morzelowski/CVE-2026-12243-NLTK-PoC.git
cd CVE-2026-12243-NLTK-PoC
docker compose build
./run.sh
```

Expected result:

```text
=== Vulnerable image: NLTK 3.9.4 ===
NLTK version       : 3.9.4
Working directory  : /app
Configured data dir: /lab/nltk_data
Encoded resource   : %2e%2e/%2e%2e/outside/lab-secret.txt
Decoded resource   : ../../outside/lab-secret.txt
Resolved candidate : /outside/lab-secret.txt
NLTK warning       : Security Violation [pathsec.open]: Unauthorized path /outside/lab-secret.txt
NLTK result        : read 36 bytes
Synthetic marker   : CVE-2026-12243-SYNTHETIC-LAB-MARKER
[PASS] Traversal escaped the configured NLTK data directory.

=== Patched image: NLTK 3.10.0 ===
NLTK version       : 3.10.0
NLTK result        : blocked (ValueError: Unsafe resource path: '...')
[PASS] Patched version rejected the same encoded traversal.

Lab completed: traversal reproduced and patched rejection verified.
```

The affected image reports that `/outside/lab-secret.txt` is unauthorized but
still returns its contents because NLTK 3.9.4 uses warning-only path security
by default. Exception and warning text can vary slightly; `run.sh` uses the
process exit status, not a fragile text match, to decide whether the
demonstration passed.

## How the demonstration works

Each image contains this deliberately separated layout:

```text
/
β”œβ”€β”€ app/
β”‚   └── poc.py          # process CWD is /app
β”œβ”€β”€ lab/
β”‚   └── nltk_data/      # configured NLTK search root
└── outside/
    └── lab-secret.txt  # public synthetic marker
```

`poc.py` replaces `nltk.data.path` with `/lab/nltk_data` and passes the fixed
resource name `%2e%2e/%2e%2e/outside/lab-secret.txt` to
`nltk.data.load(..., format="raw")`. In the affected release, decoding occurs
too late in the validation flow:

```text
/lab/nltk_data
      ↓  ../../outside/lab-secret.txt
/outside/lab-secret.txt
```

Because the working directory is `/app`, the canary is outside both locations
that matter to the demonstration: `/app` and `/lab/nltk_data`.

The script has two explicit assertions:

1. NLTK 3.9.4 must return the known synthetic marker.
2. NLTK 3.10.0 must reject the exact same resource name.

Any other result exits non-zero, so automated checks cannot report a false
success.

## Safety model

The Compose configuration intentionally limits the lab:

- `network_mode: none` disables networking while either demonstration runs.
- No host ports are published.
- No host directories or Docker socket are mounted.
- The containers run as an unprivileged user with all Linux capabilities
  dropped and `no-new-privileges` enabled.
- The root filesystem is read-only; only a small, `noexec` temporary filesystem
  is writable.
- The only disclosed value is `fixtures/lab-secret.txt`, a public test marker
  copied into the image during build.

The image build needs package-index access to install the two pinned NLTK
versions. Runtime execution is offline.

## Technical details

- **CVE:** CVE-2026-12243
- **GHSA:** GHSA-m42h-3232-vpv3
- **Weakness:** CWE-22 β€” path traversal
- **Affected:** NLTK versions before 3.10.0
- **Fixed:** NLTK 3.10.0
- **Impact:** disclosure of files readable by the application process when an
  attacker controls a resource name supplied to `nltk.data.load()` or
  `nltk.data.find()`

The lab pins 3.9.4 because it is the concrete release named in the original
report and 3.10.0 because it is the first patched release recorded by the
maintainer advisory.

## Mitigation

Upgrade NLTK and keep it current:

```bash
python -m pip install "nltk>=3.10.0"
```

Also avoid passing untrusted resource names into filesystem-loading APIs.
Where user selection is required, map user-facing identifiers to an allowlist
of application-owned resources instead of accepting paths or URLs directly.

## Manual commands

Run either side independently:

```bash
docker compose run --rm vulnerable
docker compose run --rm patched
```

Inspect the fully resolved Compose configuration:

```bash
docker compose config
```

Remove the locally built lab images:

```bash
docker compose down --rmi local
```

## Troubleshooting

- **`permission denied: ./run.sh`** β€” run `chmod +x run.sh` once.
- **`docker: command not found`** β€” install Docker Desktop or Docker Engine.
- **Package download errors during build** β€” confirm Docker has temporary
  outbound access for the build, then retry `docker compose build --no-cache`.

## References

- [GitHub maintainer advisory GHSA-m42h-3232-vpv3](https://github.com/advisories/GHSA-m42h-3232-vpv3)
- [NVD entry for CVE-2026-12243](https://nvd.nist.gov/vuln/detail/CVE-2026-12243)
- [Original NLTK issue #3504](https://github.com/nltk/nltk/issues/3504)
- [NLTK fix pull request #3522](https://github.com/nltk/nltk/pull/3522)
- [Fix commit `aec4fce`](https://github.com/nltk/nltk/commit/aec4fce1b84ad725b8975f7365b23a4f626572a9)

## License

Released under the [MIT License](LICENSE).