{"id":"CVE-2026-12243","aliases":["DEBIAN-CVE-2026-12243","EUVD-2026-40240","GHSA-m42h-3232-vpv3","GHSA-q5h6-fcf5-49g9","PYSEC-2026-597","UBUNTU-CVE-2026-12243"],"status":"rejected","title":"nltk: Arbitrary File Read via Path Traversal in nltk.data.load() through Percent-Encoded Sequences","description":"This CVE ID has been rejected or withdrawn by its CVE Numbering Authority.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high","from":"ghsa"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":true,"fix_available":true},"cwes":["CWE-22"],"published":"2026-06-30T00:14:35Z","modified":"2026-10-16T14:10:00Z","exploits":[{"source":"pocgithub","id":"morzelowski/CVE-2026-12243-NLTK-PoC","title":"morzelowski/CVE-2026-12243-NLTK-PoC","date":"2026-08-29","url":"https://github.com/morzelowski/CVE-2026-12243-NLTK-PoC"}],"fixes":[{"ecosystem":"PyPI","package":"nltk","fixed_in":["3.10.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.10.0"}]}]},{"source":"osv","ecosystem":"PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.10.0"}]}],"versions":["0.8","0.9","0.9.3","0.9.4","0.9.5","0.9.6","0.9.7","0.9.8","0.9.9","2.0.1","2.0.1rc1","2.0.1rc2-git","2.0.1rc3","2.0.1rc4","2.0.2","2.0.3","2.0.4","2.0.5","2.0b4","2.0b5","2.0b6","2.0b7","2.0b8","2.0b9","3.0.0","3.0.0b1","3.0.0b2","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.1","3.2","3.2.1","3.2.2","3.2.3","3.2.4","3.2.5","3.3","3.4","3.4.1","3.4.2","3.4.3","3.4.4","3.4.5","3.5","3.5b1","3.6","3.6.1","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","3.6.7","3.7","3.8","3.8.1","3.9","3.9.1","3.9.2","3.9.3","3.9.4","3.9b1"]},{"source":"osv","ecosystem":"PyPI","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"3.9.4"}]}],"versions":["0.8","0.9","0.9.3","0.9.4","0.9.5","0.9.6","0.9.7","0.9.8","0.9.9","2.0.1","2.0.1rc1","2.0.1rc2-git","2.0.1rc3","2.0.1rc4","2.0.2","2.0.3","2.0.4","2.0.5","2.0b4","2.0b5","2.0b6","2.0b7","2.0b8","2.0b9","3.0.0","3.0.0b1","3.0.0b2","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.1","3.2","3.2.1","3.2.2","3.2.3","3.2.4","3.2.5","3.3","3.4","3.4.1","3.4.2","3.4.3","3.4.4","3.4.5","3.5","3.5b1","3.6","3.6.1","3.6.2","3.6.3","3.6.4","3.6.5","3.6.6","3.6.7","3.7","3.8","3.8.1","3.9","3.9.1","3.9.2","3.9.3","3.9.4","3.9b1"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"nltk","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.9.1-2"]}],"references":[{"url":"https://github.com/nltk/nltk/security/advisories/GHSA-m42h-3232-vpv3","tags":["web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-12243","tags":["advisory"]},{"url":"https://github.com/nltk/nltk/issues/3504","tags":["web"]},{"url":"https://github.com/nltk/nltk/pull/3522","tags":["web"]},{"url":"https://github.com/nltk/nltk/commit/aec4fce1b84ad725b8975f7365b23a4f626572a9","tags":["web"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/nltk/PYSEC-2026-597.yaml","tags":["web"]},{"url":"https://huntr.com/bounties/39aa9354-54ca-4e77-96da-580eb1fe6ed1","tags":["web","evidence","report"]},{"url":"https://securityinfinity.com/research/path-traversal-in-nltks-nltk-data-load-via-percent-encoded-sequences","tags":["web"]},{"url":"https://github.com/advisories/GHSA-m42h-3232-vpv3","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-q5h6-fcf5-49g9"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/12xxx/CVE-2026-12243.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-12243","tags":["advisory"]},{"url":"https://github.com/nltk/nltk","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-12243","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-12243","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-12243","description":"This CVE ID has been rejected or withdrawn by its CVE Numbering Authority.","status":"rejected","published":"2026-06-30T00:14:35.37Z","modified":"2026-08-18T08:33:26.727Z","updated_at":"2026-11-02T14:19:48.461833Z"}],"euvd":[{"id":"EUVD-2026-40240","description":"This CVE ID has been rejected or withdrawn by its CVE Numbering Authority.","status":"published","published":"2026-06-30T00:14:35Z","modified":"2026-08-18T08:33:26Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"updated_at":"2026-11-02T18:01:47.222335Z"}],"ghsa":[{"id":"GHSA-m42h-3232-vpv3","title":"nltk: Arbitrary File Read via Path Traversal in nltk.data.load() through Percent-Encoded Sequences","description":"# Summary\nnltk.data.load() and nltk.data.find() resolve user-supplied resource names to filesystem paths using url2pathname(), which decodes percent-encoded sequences (e.g. %2e%2e to ..). Path safety checks are performed on the raw, still-encoded string before decoding occurs. An attacker supplying %2e%2e instead of .. bypasses all path validation and reads arbitrary files outside the NLTK data directory.\n\n# Vulnerable Code\nnltk/data.py - find() function:\n url2pathname() decodes %2e%2e -\u003e .. AFTER any safety check\np = os.path.join(path_, url2pathname(resource_name))\nif os.path.exists(p):\n    return FileSystemPathPointer(p)\n\n# Proof of Concept\nimport nltk.data\nnltk.data.path = [\"/home/user/nltk_data\"]\n%2e%2e decodes to .. via url2pathname(), escaping the data dir\ndata = nltk.data.load(\"%2e%2e/SECRET_credentials.txt\", format=\"raw\")\nprint(data)\n b'AWS_SECRET_KEY=AKIAIOSFODNN7EXAMPLE\\nDATABASE_PASS=hunter2\\n'\nAll of these bypass path checks and decode identically:\n\n# Payload\tAfter url2pathname()\n%2e%2e/secret\t../secret\n.%2e/secret\t../secret\n%2e./secret\t../secret\n%2E%2E/secret\t../secret\nRoot Cause\nurl2pathname() is called after path safety checks, not before. Encoding .. as %2e%2e passes every check, then decodes to a traversal sequence at filesystem access time.\n\n# Fix\nDecode before checking:\n\nfrom urllib.parse import unquote\nresource_name = unquote(resource_name)  # decode first, then validate\n\n# Impact\nAn attacker who controls the resource name passed to nltk.data.load() can read any file the process has permission to access - credentials, environment files, SSH private keys, /etc/passwd, /proc/self/environ, application config files, etc. This affects any application that passes user-controlled input to nltk.data.load() or nltk.data.find().","status":"published","published":"2026-08-13T20:45:05Z","modified":"2026-08-13T20:45:06Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:41:01.23108Z"},{"id":"GHSA-q5h6-fcf5-49g9","title":"Duplicate Advisory: Arbitrary File Read via Path Traversal in nltk.data.load() through Percent-Encoded Sequences","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-m42h-3232-vpv3. This link is maintained to preserve external references.\n\n## Original Description\nNLTK version 3.9.4 is vulnerable to a path traversal attack due to an incomplete fix for GitHub Issue #3504. The `_UNSAFE_NO_PROTOCOL_RE` regex in `nltk/data.py` checks for literal `../` sequences but fails to account for percent-encoded traversal sequences such as `..%2f`. The `url2pathname()` function decodes these sequences after the validation step, allowing an attacker to bypass the protection. This vulnerability enables an attacker to read arbitrary files accessible to the Python process by controlling the resource name parameter passed to `nltk.data.load()` or `nltk.data.find()`. The issue affects applications that rely on NLTK for resource loading, including NLP web applications, Jupyter notebooks, and CLI tools. The default `pathsec.ENFORCE=False` setting exacerbates the impact by not blocking the file read at the `open()` stage.","status":"withdrawn","published":"2026-06-30T03:37:14Z","modified":"2026-08-13T20:44:56Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:41:01.23108Z"}],"nvd":[{"id":"CVE-2026-12243","description":"Rejected reason: This CVE ID has been rejected or withdrawn by its CVE Numbering Authority.","status":"rejected","published":"2026-06-30T01:16:29.063Z","modified":"2026-10-16T14:10:00.12Z","updated_at":"2026-11-02T14:12:26.508751Z"}],"osv":[{"id":"CVE-2026-12243","title":"Path Traversal via Percent-Encoding in nltk.data.find() and nltk.data.load()","description":"NLTK version 3.9.4 is vulnerable to a path traversal attack due to an incomplete fix for GitHub Issue #3504. The `_UNSAFE_NO_PROTOCOL_RE` regex in `nltk/data.py` checks for literal `../` sequences but fails to account for percent-encoded traversal sequences such as `..%2f`. The `url2pathname()` function decodes these sequences after the validation step, allowing an attacker to bypass the protection. This vulnerability enables an attacker to read arbitrary files accessible to the Python process by controlling the resource name parameter passed to `nltk.data.load()` or `nltk.data.find()`. The issue affects applications that rely on NLTK for resource loading, including NLP web applications, Jupyter notebooks, and CLI tools. The default `pathsec.ENFORCE=False` setting exacerbates the impact by not blocking the file read at the `open()` stage.","status":"published","published":"2026-06-30T00:14:35.37Z","modified":"2026-08-13T21:10:37.370031268Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:44:57.354194Z"},{"id":"DEBIAN-CVE-2026-12243","description":"NLTK version 3.9.4 is vulnerable to a path traversal attack due to an incomplete fix for GitHub Issue #3504. The `_UNSAFE_NO_PROTOCOL_RE` regex in `nltk/data.py` checks for literal `../` sequences but fails to account for percent-encoded traversal sequences such as `..%2f`. The `url2pathname()` function decodes these sequences after the validation step, allowing an attacker to bypass the protection. This vulnerability enables an attacker to read arbitrary files accessible to the Python process by controlling the resource name parameter passed to `nltk.data.load()` or `nltk.data.find()`. The issue affects applications that rely on NLTK for resource loading, including NLP web applications, Jupyter notebooks, and CLI tools. The default `pathsec.ENFORCE=False` setting exacerbates the impact by not blocking the file read at the `open()` stage.","status":"withdrawn","published":"2026-06-30T01:16:29.063Z","modified":"2026-08-19T02:00:36.925242204Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"updated_at":"2026-11-02T15:45:51.374409Z"},{"id":"GHSA-m42h-3232-vpv3","title":"nltk: Arbitrary File Read via Path Traversal in nltk.data.load() through Percent-Encoded Sequences","description":"# Summary\nnltk.data.load() and nltk.data.find() resolve user-supplied resource names to filesystem paths using url2pathname(), which decodes percent-encoded sequences (e.g. %2e%2e to ..). Path safety checks are performed on the raw, still-encoded string before decoding occurs. An attacker supplying %2e%2e instead of .. bypasses all path validation and reads arbitrary files outside the NLTK data directory.\n\n# Vulnerable Code\nnltk/data.py - find() function:\n url2pathname() decodes %2e%2e -\u003e .. AFTER any safety check\np = os.path.join(path_, url2pathname(resource_name))\nif os.path.exists(p):\n    return FileSystemPathPointer(p)\n\n# Proof of Concept\nimport nltk.data\nnltk.data.path = [\"/home/user/nltk_data\"]\n%2e%2e decodes to .. via url2pathname(), escaping the data dir\ndata = nltk.data.load(\"%2e%2e/SECRET_credentials.txt\", format=\"raw\")\nprint(data)\n b'AWS_SECRET_KEY=AKIAIOSFODNN7EXAMPLE\\nDATABASE_PASS=hunter2\\n'\nAll of these bypass path checks and decode identically:\n\n# Payload\tAfter url2pathname()\n%2e%2e/secret\t../secret\n.%2e/secret\t../secret\n%2e./secret\t../secret\n%2E%2E/secret\t../secret\nRoot Cause\nurl2pathname() is called after path safety checks, not before. Encoding .. as %2e%2e passes every check, then decodes to a traversal sequence at filesystem access time.\n\n# Fix\nDecode before checking:\n\nfrom urllib.parse import unquote\nresource_name = unquote(resource_name)  # decode first, then validate\n\n# Impact\nAn attacker who controls the resource name passed to nltk.data.load() can read any file the process has permission to access - credentials, environment files, SSH private keys, /etc/passwd, /proc/self/environ, application config files, etc. This affects any application that passes user-controlled input to nltk.data.load() or nltk.data.find().","status":"published","published":"2026-08-13T20:45:05Z","modified":"2026-08-13T21:10:37.370031268Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:51.10002Z"},{"id":"GHSA-q5h6-fcf5-49g9","title":"Duplicate Advisory: Arbitrary File Read via Path Traversal in nltk.data.load() through Percent-Encoded Sequences","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-m42h-3232-vpv3. This link is maintained to preserve external references.\n\n## Original Description\nNLTK version 3.9.4 is vulnerable to a path traversal attack due to an incomplete fix for GitHub Issue #3504. The `_UNSAFE_NO_PROTOCOL_RE` regex in `nltk/data.py` checks for literal `../` sequences but fails to account for percent-encoded traversal sequences such as `..%2f`. The `url2pathname()` function decodes these sequences after the validation step, allowing an attacker to bypass the protection. This vulnerability enables an attacker to read arbitrary files accessible to the Python process by controlling the resource name parameter passed to `nltk.data.load()` or `nltk.data.find()`. The issue affects applications that rely on NLTK for resource loading, including NLP web applications, Jupyter notebooks, and CLI tools. The default `pathsec.ENFORCE=False` setting exacerbates the impact by not blocking the file read at the `open()` stage.","status":"withdrawn","published":"2026-06-30T03:37:14Z","modified":"2026-09-10T03:50:50.203051003Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:54.055966Z"},{"id":"PYSEC-2026-597","description":"NLTK version 3.9.4 is vulnerable to a path traversal attack due to an incomplete fix for GitHub Issue #3504. The `_UNSAFE_NO_PROTOCOL_RE` regex in `nltk/data.py` checks for literal `../` sequences but fails to account for percent-encoded traversal sequences such as `..%2f`. The `url2pathname()` function decodes these sequences after the validation step, allowing an attacker to bypass the protection. This vulnerability enables an attacker to read arbitrary files accessible to the Python process by controlling the resource name parameter passed to `nltk.data.load()` or `nltk.data.find()`. The issue affects applications that rely on NLTK for resource loading, including NLP web applications, Jupyter notebooks, and CLI tools. The default `pathsec.ENFORCE=False` setting exacerbates the impact by not blocking the file read at the `open()` stage.","status":"published","published":"2026-06-30T01:16:29.063Z","modified":"2026-08-19T12:15:03.3218699Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"updated_at":"2026-11-02T15:52:57.671918Z"},{"id":"UBUNTU-CVE-2026-12243","description":"Rejected reason: This CVE ID has been rejected or withdrawn by its CVE Numbering Authority.","status":"published","published":"2026-06-30T01:16:00Z","modified":"2026-09-02T19:35:27.823984326Z","cvss":[{"version":"3.0","score":7.5,"vector":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","level":"high"}],"updated_at":"2026-11-02T16:56:00.592716Z"}]}}
