---
id: CVE-2026-81726
aliases:
  - GHSA-8mgp-746c-j5xp
  - PYSEC-2026-3740
title: 'NLTK: Model-artifact APIs bypass pathsec and touch files outside allowed roots'
summary: 'NLTK: Model-artifact APIs bypass pathsec and touch files outside allowed roots'
severity: high
cvss: 7
cvssVector: 'CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:L'
vendor: nltk
product: nltk
ecosystem: pip
affected:
  - nltk < 3.10.4
patched:
  - nltk 3.10.4
published: '2026-09-02'
updated: '2026-11-02'
sourceUpdated: '2026-11-02T22:15:04.414504485Z'
source: OSV
sourceUrl: 'https://osv.dev/vulnerability/GHSA-8mgp-746c-j5xp'
references:
  - url: 'https://github.com/nltk/nltk/security/advisories/GHSA-8mgp-746c-j5xp'
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-81726'
  - url: 'https://github.com/nltk/nltk/pull/3757'
  - url: 'https://github.com/nltk/nltk/pull/3759'
  - url: 'https://github.com/nltk/nltk/pull/3813'
  - url: >-
      https://github.com/nltk/nltk/commit/2a92b71827d754ae8920261e7ed0c4bb283ab2d7
  - url: >-
      https://github.com/nltk/nltk/commit/a44a7af69bca87e92d9c4a701fcbbe4512e8d450
  - url: >-
      https://github.com/nltk/nltk/commit/cbc98458b43de5f792f0382583c16df39e5c5117
  - url: 'https://github.com/nltk/nltk'
  - url: >-
      https://github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-3740.yaml
  - url: >-
      https://www.vulncheck.com/advisories/nltk-through-3.10.3-path-traversal-via-model-artifact-apis
  - url: 'https://github.com/advisories/GHSA-8mgp-746c-j5xp'
  - url: >-
      https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-81726.json
  - url: 'https://access.redhat.com/security/cve/CVE-2026-81726'
  - url: 'https://bugzilla.redhat.com/show_bug.cgi?id=2525022'
  - url: 'https://www.cve.org/CVERecord?id=CVE-2026-81726'
  - url: 'https://access.redhat.com/errata/RHSA-2026:84734'
tags:
  - osv
  - pip
  - ghsa
  - csaf
  - vex
  - red-hat
epss: 0.00339
epssPercentile: 0.27448
cwe:
  - CWE-22
  - CWE-59
  - CWE-73
scores:
  osv: 7
  ghsa: 7
  vendor: 8.7
ingestedAt: '2026-09-02T14:45:30.305Z'
---

## Overview

### Summary

Several model-artifact APIs still treat caller-controlled model paths as ordinary filenames even when NLTK path security is enforced. The same outside-root paths are rejected by guarded helpers, but these public read and write flows still use raw file APIs.

### Details

- **Vulnerability type:** File sandbox bypass
- **Affected component:** `TransitionParser.train`, `TransitionParser.parse`, `AveragedPerceptron.save`, `AveragedPerceptron.load`, `PerceptronTagger.save_to_json`, `save_maxent_params`
- **Affected versions:** Published `3.9.4` and current source `v3.10.0-rc2` both reproduced.
- **Patched versions:** Not yet patched
- **Root cause:** Model import and export helpers use built-in `open()` on caller-controlled paths instead of pathsec-aware helpers.

`TransitionParser.train()` writes outside allowed roots, `TransitionParser.parse()` reads outside allowed roots, `AveragedPerceptron` bypasses the sandbox in both directions, and adjacent read-side helpers in the same family already show the intended guarded behavior. I confirmed outside-root reads and writes while `pathsec.open()` or the guarded sibling helpers rejected the same paths.

### PoC

**Preconditions**
- The application enables `pathsec` enforcement and lets untrusted workflows choose model import or export paths.

**Steps**
1. Enable `pathsec.ENFORCE=True` and restrict allowed roots to a dedicated sandbox directory.
2. Use public model import or export APIs with paths that point outside that root.
3. Observe the same paths are rejected by negative-control guarded helpers such as `pathsec.open()`, `PerceptronTagger.load_from_json()`, or `load_maxent_params()`.
4. Observe the vulnerable APIs still read or write outside-root files successfully.

**Minimal reproducible excerpt**

```text
transition_train_exists True
transition_parse_loader_read_bytes 13
averaged_load_keys ['bias']
maxent_save wrote ['alwayson.tab', 'labels.txt']
```

### Impact

Consumers that rely on `pathsec` for local containment can be tricked into reading or overwriting files outside approved roots through normal model persistence and loading APIs.

### Remediation

Route all model-path file access through `nltk.pathsec.open()` or existing pathsec-aware helpers, and add regression tests that pair each vulnerable API with a negative control on the same path.

### References

- https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/parse/transitionparser.py#L551-L571
- https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/tag/perceptron.py#L106-L113
- https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/tag/perceptron.py#L262-L273
- https://github.com/nltk/nltk/blob/v3.10.0-rc2/nltk/classify/maxent.py#L1583-L1602

## Affected packages

- `nltk < 3.10.4`

## Remediation

Upgrade to a patched release:

- `nltk 3.10.4`

## Vendor advisories

- **RHSA-2026:84734** · Red Hat · fixed in: Red Hat OpenShift AI 3.4 · released 2026-10-19 · [advisory](https://access.redhat.com/errata/RHSA-2026:84734)
- **Red Hat VEX** · Important · affected: Exploit Intelligence, Lightspeed Core, OpenShift Lightspeed, Red Hat Ansible Automation Platform 2, Red Hat OpenShift AI (RHOAI) · no fix planned: Exploit Intelligence, OpenShift Lightspeed, Red Hat Ansible Automation Platform 2, Lightspeed Core, … · updated 2026-10-19 · [vex](https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-81726.json)
