Skip to content

Possible fix(deps): 79 vulnerable dependencies in uv.lock #67

Description

@begininvoke

This might be a false positive, but exploitation/garak/uv.lock around line 1 looked worth a second pair of eyes.

CRITICAL — CVE-2025-14009: NLTK 3.9.2 (pinned in exploitation/garak/uv.lock as a dependency of garak) contains an unsafe archive-extraction flaw (zip-slip + untrusted code execution). The _unzip_iter function in nltk/downloader.py calls zipfile.extractall() without validating archive member paths or content, implicitly trusting every downloaded NLTK data package. An attacker who can control or tamper with the package source (MITM on the download channel, a compromised/malicious index, or a poisoned NLTK_DATA cache) can craft a zip containing path-traversal entries (writing files outside the target directory) or Python files such as __init__.py, which execute automatically on import — resulting in remote code execution with the privileges of the process, including filesystem access, network access, and persistence. Exposure is triggered whenever nltk.download() is invoked (garak downloads tokenizer/corpus data on first use), making this exploitable in developer machines, CI, and any runtime that pulls NLTK data. Risk level: CRITICAL — arbitrary code execution via a widely used dependency. Fixed in nltk 3.9.3; remediation is a version bump in the lockfile plus defense-in-depth around NLTK data downloads.

Something like this might fix it:

Upgrade the locked nltk version and let `uv` regenerate hashes (do not hand-edit uv.lock):

```bash
# From exploitation/garak/
uv lock --upgrade-package nltk   # re-resolves nltk 3.9.2 -> 3.9.3 and recomputes hashes
uv sync                          # rebuild the environment against the updated lockfile
# If nltk is a direct dependency in pyproject.toml instead:
uv add 'nltk>=3.9.3'
```

Resulting diff in exploitation/garak/uv.lock:

```diff
--- a/exploitation/garak/uv.lock
+++ b/exploitation/garak/uv.lock
@@
 [[package]]
 name = "nltk"
-version = "3.9.2"
+version = "3.9.3"
 source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/.../nltk-3.9.2.tar.gz", hash = "sha256:<old-hash>" }
+sdist = { url = "https://files.pythonhosted.org/packages/.../nltk-3.9.3.tar.gz", hash = "sha256:<new-hash>" }
 wheels = [
-    { url = "https://files.pythonhosted.org/packages/.../nltk-3.9.2-py3-none-any.whl", hash = "sha256:<old-hash>" },
+    { url = "https://files.pythonhosted.org/packages/.../nltk-3.9.3-py3-none-any.whl", hash = "sha256:<new-hash>" },
 ]
```

If nltk is only a transitive dependency (garak -> nltk) and a resolver constraint keeps it back, force the patched version via an override in pyproject.toml:

```diff
--- a/exploitation/garak/pyproject.toml
+++ b/exploitation/garak/pyproject.toml
@@
+[tool.uv]
+override-dependencies = ["nltk>=3.9.3"]
```

Then commit the regenerated uv.lock. Defense-in-depth (since the flaw lives in the download+extract path): avoid calling `nltk.download()` in CI/production — vendor NLTK data into the image via NLTK_DATA from a trusted, hash-verified source instead, and pin/verify the download server if downloads are unavoidable.

For reference: rule CVE-2025-14009. Rated critical.

I may be wrong about this one — closing it costs you nothing if so.


Found with automated scanning (RedGem) and reviewed before opening. If it is not useful, closing it is completely fine.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions