Safeguard
Supply Chain•

Can pip hash checking protect an ML environment?

pip hash checking verifies each download against hashes you store and fails on anything unpinned. What it covers, what it does not, and how to adopt it.

Safeguard Security Team
4 min read

Partly. pip's hash checking mode verifies every downloaded package against hashes stored in your requirements file, and fails on anything unpinned or unlisted. That guards against tampered downloads and surprise dependencies. It does not tell you a package is safe, only that it is the same file you approved.

How the mode works

According to the pip documentation, adding a hash option to any requirement turns on hash checking globally. You can also force it with the require hashes command line flag. Rules from the docs:

  • Hashes are required for all requirements. A partially hashed file could let a malicious actor slip code in through an unhashed line.
  • Every dependency must be spelled out and hashed. An unlisted dependency causes an error.
  • Requirements must be pinned, using double equals, a URL or a file path.
  • Hashes served in PyPI download URLs do not count, because they come from the remote source.
  • sha256 is recommended. Weaker algorithms such as md5, sha1 and sha224 are excluded.

The docs say the protection is against remote tampering and network issues.

What it gives an ML team

ML environments pull large dependency trees: numerical libraries, deep learning frameworks, tokenizers, data tools. With hash checking, a rebuild a month later fetches the same bytes you tested, or it fails loudly. That is good for reproducibility as well as security.

ThreatDoes hash checking help?
A file swapped after you approved itYes
A new transitive dependency appearingYes, it errors
A malicious package you approved by mistakeNo
A typosquatted package you typed on purposeNo
A vulnerable version you pinnedNo

The last three are why hashes complement review and scanning rather than replace them.

How to adopt it

  1. Choose a source of truth: a lock file from a tool that can write hashes, or a compiled requirements file.
  2. Generate the file on a clean machine from a reviewed top level list.
  3. Check that every line has a version and at least one sha256 hash.
  4. Install in CI with the require hashes flag so a missing hash fails the build.
  5. Regenerate on a schedule, review the diff, and scan the new set.

A command shape for the final install step:

pip install -r requirements.txt --require-hashes

Rough edges with GPU packages

Framework wheels are often served from a separate index and differ by platform and accelerator version, so a hash list built on one machine may not match another. Generate hashes for each target platform you deploy to, and keep the files separate. The docs also mention that from pip 26.2 a flag can disable automatic enforcement for local directories and version control URLs, so check your pip version before relying on behavior.

Also read why pip extra index url is unsafe for private packages, since index choice and hashes work together.

Safeguard's dependency scanning and SBOM tooling can inventory the set you lock, and a free scan is at gold.safeguard.sh/scan.

Try it yourself

Click through it at your own pace, or open it full screen. Notice how direct and transitive packages are listed together.

Quick check

Do I need to hash every package?

Yes. The docs say hashes are required for all requirements, direct and transitive.

Does a matching hash mean the package is safe?

No. It means the file is the one you recorded.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.