Safeguard
Developer Tools•

Does pip freeze pin transitive dependencies, and is that enough?

pip freeze records every installed package with an exact version, direct and transitive. See what it misses, such as hashes, and how to harden the output.

Safeguard Security Team
3 min read

Yes. pip freeze writes every package in the environment with an exact version, including transitive dependencies, so it pins more than the top level packages you chose. It is a start, but it carries no hashes, no platform logic and no record of where each file came from.

What the documentation says

pip's repeatable installs guide describes pinning with the double equals operator, which protects you from bugs or incompatibilities in newly released versions. Freeze generates a pinned requirements file, and the guide says this pins not only the top level packages but also all their transitive dependencies. Installing with the no dependencies option adds protection against pulling in anything the file does not list.

What freeze gives you and what it does not

Propertypip freeze output
Exact versionsYes
Transitive packagesYes
HashesNo
Records which are direct choicesNo
Works across platformsOnly for the platform it ran on
Source index recordedNo

The guide itself says pinning trusts the places you fetch from, relying on those sources not changing packages without a version bump. Hash checking is how you stop trusting that. The guide says hash-checking mode guards against a compromised index or certificate chain and against packages changing without a version change.

Why the output also hides intent

A frozen file mixes your choices with their dependencies in one flat list. In six months nobody can tell which line you asked for and which came along. That makes removal and review harder. A better flow keeps a short input file of direct dependencies and generates the pinned file from it with a lock tool.

Steps to improve a frozen file

  1. Keep a separate, short list of direct dependencies.
  2. Generate the pinned list from it, with hashes. See how to generate hashes for a Python requirements file.
  3. Install from that file with the environment variable PIP_NO_DEPS set so unlisted packages cannot join.
  4. Rebuild on purpose in a reviewed change.
  5. Scan the pinned set on a schedule, because pinned versions age.

Freeze in a clean environment

The output reflects whatever is installed, including tools you added by hand. Run freeze only in an environment built from your declared dependencies, never in one you have been experimenting in. Otherwise stray packages end up pinned into production, and you will be scanning and updating things you do not use.

Try it yourself

Click through it at your own pace, or open it full screen. Compare the flat list with how direct and transitive components are shown.

Quick check

Is a frozen requirements file a lock file?

It is close, but it has no hashes or platform information. A lock tool records more.

Will a pinned version stay safe?

No. New advisories can appear against a version you pinned, so keep scanning.

Safeguard's SBOM and dependency scanning matches a pinned set against new advisories, and a free scan takes a requirements file.

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.