I tried out Python package vulnerability auditing (uv audit) and malware checking (UV_MALWARE_CHECK) with uv
This page has been translated by machine translation. View original
uv is becoming the de facto standard for setting up Python environments.
In June 2026, uv added two security-related features in preview.
Vulnerability and malware checks in uv@Published June 8, 2026
uv auditis a command that checks whether dependent packages have vulnerabilities or are affected by quarantine — it's essentially the uv version ofpip-audit- Setting the environment variable
UV_MALWARE_CHECK=1causesuv syncanduv addto query malware advisories each time they run, and if the package being installed appears in a malware advisory, the operation is aborted
Let's try out these two features in uv version 0.11.25.
Auditing packages with uv audit
We'll create a test project with intentionally pinned vulnerable versions and audit it.
$ cd /tmp
$ uv init uv-audit-test
$ cd uv-audit-test
$ uv add "aiohttp==3.14.0"
$ uv audit
uv audit is a preview feature, and running it as-is will produce an experimental warning. Add --preview-features audit only if you want to suppress the warning. The output begins with a summary line at the top.
Found 9 known vulnerabilities and no adverse project statuses in 9 packages
This is followed by the vulnerabilities listed per package. IDs are in GHSA / PYSEC / CVE format, along with the fixed version and the advisory URL.
Vulnerabilities:
aiohttp 3.14.0 has 9 known vulnerabilities:
- GHSA-4fvr-rgm6-gqmc: aiohttp: HTTP/1 Pipelined Requests Queue Without Limit
Fixed in: 3.14.1
Advisory information: https://github.com/aio-libs/aiohttp/security/advisories/GHSA-4fvr-rgm6-gqmc
- GHSA-4m7w-qmgq-4wj5: aiohttp: TLS Server Hostname Override Is Ignored When Reusing HTTPS Connections
Fixed in: 3.14.1
Advisory information: https://github.com/aio-libs/aiohttp/security/advisories/GHSA-4m7w-qmgq-4wj5
- GHSA-xcgm-r5h9-7989: aiohttp: Incomplete websocket frame payloads bypass memory limits
Fixed in: 3.14.1
Advisory information: https://github.com/aio-libs/aiohttp/security/advisories/GHSA-xcgm-r5h9-7989
- PYSEC-2026-237: No summary provided
Fixed in: 3.14.1
Advisory information: https://github.com/aio-libs/aiohttp/security/advisories/GHSA-4m7w-qmgq-4wj5
...
When vulnerabilities are found, the exit code is 1.
Upgrading aiohttp to 3.14.1 eliminates the vulnerability reports.
$ uv audit
Found no known vulnerabilities and no adverse project statuses in 9 packages
$ echo $?
0
Detecting malware-infected versions with UV_MALWARE_CHECK=1
Running uv add or uv sync with the environment variable UV_MALWARE_CHECK=1 checks whether the version is affected by malware.
As a test package, we'll use version 4.87.1 of the Telnyx Python SDK, which suffered a supply chain attack in March 2026.
Telnyx Python SDK Security Notice: Malicious PyPI Versions Identified (March 2026)
The compromised version has already been removed from the package registry (PyPI).
$ UV_MALWARE_CHECK=1 uv add "telnyx==4.87.1"
× No solution found when resolving dependencies:
╰─▶ Because there is no version of telnyx==4.87.1 and your project depends on telnyx==4.87.1, we can conclude that your project's
requirements are unsatisfiable.
hint: If you want to add the package regardless of the failed resolution, provide the `--frozen` flag to skip locking and syncing
For this reason, we'll prepare a test uv.lock file, pass the --frozen option to skip resolution, and attempt installation treating the lock file as the source of truth.
Prepare the following uv.lock.
version = 1
revision = 3
requires-python = ">=3.14"
[[package]]
name = "uv-mal-repro"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "telnyx" },
]
[package.metadata]
requires-dist = [{ name = "telnyx" }]
[[package]]
name = "telnyx"
version = "4.87.1"
source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/00/00/telnyx-4.87.1-py3-none-any.whl", hash = "sha256:0000000000000000000000000000000000000000000000000000000000000000", size = 1000 },
]
Next, prepare the following pyproject.toml.
[project]
name = "uv-mal-repro"
version = "0.1.0"
requires-python = ">=3.14"
dependencies = ["telnyx==4.87.1"]
When running uv sync, malware is detected and the process exits with an error, even though the wheels URL in the lock file is a dummy.
This is because the malware check runs before the download and queries OSV using the package name and version.
$ UV_MALWARE_CHECK=1 uv sync --frozen
Using CPython 3.14.4
Creating virtual environment at: .venv
warning: Malware checks are experimental and may change without warning. Pass `--preview-features malware-check` to disable this warning.
warning: Malware detected in locked dependencies:
- `telnyx==4.87.1`: MAL-2026-2254 (https://osv.dev/vulnerability/MAL-2026-2254)
error: Malware detected in one or more dependencies that would be installed; aborting sync. Set `UV_MALWARE_CHECK=0` to bypass this
check.
$ echo $?
2
Where does the vulnerability data come from?
Open Source Vulnerabilities (OSV), which uv queries against, is a distributed database that aggregates vulnerability advisories across various language ecosystems. MAL advisories for malware are also held by OSV.
As you can see from uv audit outputs like PYSEC-2026-237 and GHSA-4fvr-rgm6-gqmc, OSV aggregates vulnerability information from multiple sources, including the Python Packaging Advisory Database (PYSEC) and the GitHub Advisory Database (GHSA).
Summary
We introduced uv audit for vulnerability auditing and UV_MALWARE_CHECK=1 for malware checking, both added as preview features to the Python package manager uv.
It's convenient to be able to audit for vulnerabilities and malware entirely within the uv ecosystem on the client side, leaving the GitHub side to Dependabot and similar tools.
Looking at the roadmap, support for requirements.txt in addition to uv.lock, as well as the addition of vulnerability databases beyond OSV, appear to be under consideration. We look forward to future developments.