CVE-2026-12072
Summary
A path-traversal vulnerability in NKJPCorpusReader allows an attacker who can
influence the fileids argument of its public read methods (header, raw,
words, sents, tagged_words) to read files outside the corpus root. The
reader builds the file path with no containment check and opens it with the
builtin open(), so it bypasses NLTK's nltk.pathsec sandbox — including the
strict ENFORCE = True mode that SECURITY.md recommends for web/multi-tenant
deployments. header() returns the parsed content of the out-of-root file to
the caller (arbitrary file read).
Details
SECURITY.md promises that file access is "validated against allowed NLTK data
directories" and that with nltk.pathsec.ENFORCE = True "unauthorized file
access … will raise PermissionError." That guarantee is enforced via
FileSystemPathPointer.open() / CorpusReader.open(), which call
nltk.pathsec.validate_path(...).
NKJPCorpusReader never uses that protected path. In
nltk/corpus/reader/nkjp.py:
- add_root() builds the path by plain string concatenation with no
normalization or containment check:
def add_root(self, fileid): # lines 96-102
if self.root in fileid:
return fileid # attacker-controlled value returned unchanged
return self.root + fileid # plain concat, '..' not stripped
- The header view appends a fixed basename and passes the string straight into
the corpus view (which opens it with the builtin open()):
class NKJPCorpus_Header_View(XMLCorpusView): # line 181
def init(self, filename, **kwargs):
XMLCorpusView.init(self, filename + "header.xml", self.tagspec) # line 189
- The other modes reach the filesystem through XML_Tool, which uses a raw
os.path.join (not the hardened FileSystemPathPointer.join()) and the
builtin open():
class XML_Tool: # line 243
def init(self, root, filename):
self.read_file = os.path.join(root, filename) # line 251
def build_preprocessed_file(self):
fr = open(self.read_file) # line 256 — pathsec never consulted
Because open() is the builtin (not PathPointer.o
⚡ Watch CVE-2026-12072
Get an email if CVE-2026-12072 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.
Advisory coverage (1)
External references
Embed the live status
— this badge updates automatically when the KEV or exploit status changes. How to embed it →
[](https://www.csirts.com/cve/CVE-2026-12072)