# uv's Malware Check: What It Blocks and What It Misses


When [litellm was compromised](https://pydevtools.com/blog/litellm-supply-chain-attack-and-securing-python-dependencies.md) in March, the malicious versions sat on PyPI for hours. When [lightning was hit](https://pydevtools.com/blog/lightning-pypi-compromise-import-time-supply-chain-attack.md) in April, Socket flagged the bad releases 18 minutes after upload. Any `uv sync` inside those windows installed the malware. [uv](https://pydevtools.com/handbook/reference/uv.md) has a defense for the tail end of these incidents: an install-time check that refuses to install any package version with a published malware advisory. As of [uv 0.11.31](https://github.com/astral-sh/uv/releases/tag/0.11.31), you can turn it on in `pyproject.toml` instead of hoping every developer remembers an environment variable.

## Turn it on for the whole project

Add two lines to `pyproject.toml`:

```toml
[tool.uv.audit]
malware-check = true
```

Everyone who clones the project and runs `uv sync` now gets the check, including CI. The `UV_MALWARE_CHECK=1` environment variable (available since 0.11.16) still works for one-off sessions or pipelines where you'd rather not touch project config.

## What does the check do?

On every command that syncs the environment (`uv add`, `uv sync`, and others), uv looks up the locked packages against the MAL advisories in the [OSV](https://osv.dev/) database, sourced from the OpenSSF [malicious-packages](https://github.com/ossf/malicious-packages) project. If a locked version matches an advisory, uv stops the sync before the package lands in your environment. The litellm payload ran at interpreter startup; the lightning payload ran on `import`. A package that never gets installed does neither.

The lookup is cheap: on a small project, sync output reports `Checked 1 package in 0.39ms`.

Organizations with their own advisory feed can point `malware-check-url` at an internal endpoint instead of the default `api.osv.dev`.

## Where does it fall short?

- **It only blocks known malware.** The check matches published advisories, and advisories lag uploads. Socket's scanner caught the lightning compromise in 18 minutes, but an advisory must be filed and propagated to OSV before uv can act. A sync inside that gap passes the check. A [dependency cooldown](https://pydevtools.com/handbook/explanation/what-is-a-dependency-cooldown.md) covers the gap: `exclude-newer = "7 days"` keeps brand-new versions out until the ecosystem has vetted them.
- **It needs the network.** Each sync queries the advisory service, so the check assumes access to `api.osv.dev` or a mirror you host via `malware-check-url`. Air-gapped builds don't get it for free.
- **It only covers project syncs.** The check inspects packages in the project's [lockfile](https://pydevtools.com/handbook/explanation/what-is-a-lock-file.md). Installs through `uv pip install` and `uv tool install` don't go through that path.
- **It's a preview feature.** Sync output warns that malware checks "may change without warning," and the config settings shipped hours ago. Expect the interface to move before it stabilizes.

None of these are reasons to skip it. The check costs milliseconds and blocks the exact attack that hit litellm and lightning users. Enable it, then add a cooldown for the advisory gap, and you've covered both halves of the timeline. The [supply chain how-to](https://pydevtools.com/handbook/how-to/how-to-protect-against-python-supply-chain-attacks-with-uv.md) walks through the full setup.

## Learn more

- [How to Protect Against Python Supply Chain Attacks with uv](https://pydevtools.com/handbook/how-to/how-to-protect-against-python-supply-chain-attacks-with-uv.md)
- [How to Scan Python Dependencies for Vulnerabilities](https://pydevtools.com/handbook/how-to/how-to-scan-python-dependencies-for-vulnerabilities.md) covers `uv audit`, the after-the-fact companion to the install-time check.
- [Vulnerability and malware checks in uv](https://astral.sh/blog/uv-audit) is Astral's announcement of the feature.
- [uv audit settings reference](https://docs.astral.sh/uv/reference/settings/#audit)
