Commit 799d51a
chore(deps): update dependency nltk to v3.9.4 [security] (#329)
This PR contains the following updates:
| Package | Change | Age | Confidence |
|---|---|---|---|
| [nltk](https://www.nltk.org/)
([source](https://redirect.github.com/nltk/nltk)) | `3.9.3` -> `3.9.4` |
[](https://docs.renovatebot.com/merge-confidence/)
|
[](https://docs.renovatebot.com/merge-confidence/)
|
### GitHub Vulnerability Alerts
####
[CVE-2026-33230](https://redirect.github.com/nltk/nltk/security/advisories/GHSA-gfwx-w7gr-fvh7)
### Summary
`nltk.app.wordnet_app` contains a reflected cross-site scripting issue
in the `lookup_...` route. A crafted `lookup_<payload>` URL can inject
arbitrary HTML/JavaScript into the response page because
attacker-controlled `word` data is reflected into HTML without escaping.
This impacts users running the local WordNet Browser server and can lead
to script execution in the browser origin of that application.
### Details
The vulnerable flow is in `nltk/app/wordnet_app.py`:
-
[`nltk/app/wordnet_app.py:144`](/mnt/Data/my_brains/test/nltk/nltk/app/wordnet_app.py#L144)
- Requests starting with `lookup_` are handled as HTML responses:
- `page, word = page_from_href(sp)`
-
[`nltk/app/wordnet_app.py:755`](/mnt/Data/my_brains/test/nltk/nltk/app/wordnet_app.py#L755)
- `page_from_href()` calls `page_from_reference(Reference.decode(href))`
-
[`nltk/app/wordnet_app.py:769`](/mnt/Data/my_brains/test/nltk/nltk/app/wordnet_app.py#L769)
- `word = href.word`
-
[`nltk/app/wordnet_app.py:796`](/mnt/Data/my_brains/test/nltk/nltk/app/wordnet_app.py#L796)
- If no results are found, `word` is inserted directly into the HTML
body:
- `body = "The word or words '%s' were not found in the dictionary." %
word`
This is inconsistent with the `search` route, which does escape user
input:
-
[`nltk/app/wordnet_app.py:136`](/mnt/Data/my_brains/test/nltk/nltk/app/wordnet_app.py#L136)
- `word = html.escape(...)`
As a result, a malicious `lookup_...` payload can inject script into the
response page.
The issue is exploitable because:
- `Reference.decode()` accepts attacker-controlled base64-encoded pickle
data for the URL state.
- The decoded `word` is reflected into HTML without `html.escape()`.
- The server is started with `HTTPServer(("", port), MyServerHandler)`,
so it listens on all interfaces by default, not just `localhost`.
### PoC
1. Start the WordNet Browser in an isolated Docker environment:
```bash
docker run -d --name nltk-wordnet-web -p 8002:8002 \
nltk-sandbox \
python -c "import nltk; nltk.download('wordnet', quiet=True); from nltk.app.wordnet_app import wnb; wnb(8002, False)"
```
2. Use the following crafted payload, which decodes to:
```python
("<script>alert(1)</script>", {})
```
Encoded payload:
```text
gAWVIQAAAAAAAACMGTxzY3JpcHQ-YWxlcnQoMSk8L3NjcmlwdD6UfZSGlC4=
```
3. Request the vulnerable route:
```bash
curl -s "http://127.0.0.1:8002/lookup_gAWVIQAAAAAAAACMGTxzY3JpcHQ-YWxlcnQoMSk8L3NjcmlwdD6UfZSGlC4="
```
4. Observed result:
```text
The word or words '<script>alert(1)</script>' were not found in the dictionary.
```
<img width="867" height="208" alt="127"
src="https://github.com/user-attachments/assets/ec09da08-09bc-4fc4-bfc1-c4489e9adaf6"
/>
I also validated the issue directly at function level in Docker:
```python
import base64
import pickle
from nltk.app.wordnet_app import page_from_href
payload = base64.urlsafe_b64encode(
pickle.dumps(("<script>alert(1)</script>", {}), -1)
).decode()
page, word = page_from_href(payload)
print(word)
print("<script>alert(1)</script>" in page)
```
Observed output:
```text
WORD= <script>alert(1)</script>
HAS_SCRIPT= True
```
### Impact
This is a reflected XSS issue in the NLTK WordNet Browser web UI.
An attacker who can convince a user to open a crafted `lookup_...` URL
can execute arbitrary JavaScript in the origin of the local WordNet
Browser application. This can be used to:
- run arbitrary script in the browser tab
- manipulate the page content shown to the user
- issue same-origin requests to other WordNet Browser routes
- potentially trigger available UI actions in that local app context
This primarily impacts users who run `nltk.app.wordnet_app` as a local
or self-hosted HTTP service and open attacker-controlled links.
---
### Release Notes
<details>
<summary>nltk/nltk (nltk)</summary>
###
[`v3.9.4`](https://redirect.github.com/nltk/nltk/compare/3.9.3...3.9.4)
[Compare
Source](https://redirect.github.com/nltk/nltk/compare/3.9.3...3.9.4)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "" in timezone UTC, Automerge - At any
time (no schedule defined).
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Renovate
Bot](https://redirect.github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJweXRob24iLCJyZW5vdmF0ZSJdfQ==-->
Co-authored-by: Renovate Bot <renovate@whitesourcesoftware.com>1 parent 54989a7 commit 799d51a
1 file changed
Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments