How to Verify Dependencies with Hashes in uv
Dependency hashes let uv verify that every downloaded artifact matches what was resolved, catching tampering before anything gets installed.
Hashes in uv.lock
uv.lock includes SHA-256 hashes for every distribution by default. After running uv lock or uv add, each entry in the lockfile contains hashes for both sdists and wheels:
[[package]]
name = "certifi"
version = "2026.2.25"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "...", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" }
wheels = [
{ url = "...", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa" },
]When uv sync or uv run installs packages, it checks each downloaded artifact against these hashes. If a hash does not match, installation fails.
Hashes in requirements.txt
Some deployment workflows use requirements.txt instead of uv.lock. Two commands produce requirements files with hashes.
uv pip compile with the --generate-hashes flag:
uv pip compile pyproject.toml --generate-hashes -o requirements.txtThis produces output like:
certifi==2026.2.25 \
--hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \
--hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7uv export includes hashes by default:
uv export -o requirements.txtTo omit hashes, pass --no-hashes.
What hashes protect against
Hash verification guards against artifacts that have been altered after resolution. This covers tampering in transit (man-in-the-middle attacks) and corrupted or malicious mirrors and caches.
Important
Hashes do not protect against a malicious package uploaded directly to PyPI. If an attacker publishes a compromised version through legitimate channels, the hashes will match because they were generated from the compromised artifact itself. For that threat, consider using --exclude-newer to avoid installing recently published versions.
Hash pinning works best alongside other supply-chain protections. A lockfile pins exact versions, while dependency cooldowns add a time-based filter against recently published packages.
Get Python tooling updates
Subscribe to the newsletter