VNX-PY-001 – Missing Python Lock File
Overview
This rule fires when a Python project has a pyproject.toml or Pipfile but no corresponding lock file (uv.lock, poetry.lock, or Pipfile.lock). Lock files record the exact resolved versions and integrity hashes of every dependency in the tree. Without one, each new install can silently pull a different version of any transitive dependency — including one that has been compromised or typosquatted. This maps to CWE-829: Inclusion of Functionality from Untrusted Control Sphere.
Severity: High | CWE: CWE-829 – Inclusion of Functionality from Untrusted Control Sphere
Why This Matters
Without a lock file, floating version ranges such as requests>=2.28 or numpy~=1.24 are re-resolved on every fresh install. An attacker who publishes a malicious version of any package in your dependency tree — or who compromises a package maintainer account — can have their code pulled into your production builds without any visible change to your repository. This is the attack class described by MITRE ATT&CK T1195.001 (Supply Chain Compromise: Compromise Software Dependencies) and was demonstrated by real incidents such as the event-stream and PyTorch nightly supply chain attacks.
Even without a malicious actor, non-deterministic resolution means your CI/CD pipeline may test against one set of dependencies while production runs a different one. Reproducing bugs becomes harder, and security patches applied to a transitive dependency may or may not take effect depending on when a fresh install is triggered.
What Gets Flagged
The rule fires on a Pipfile with no Pipfile.lock beside it (reported on its [packages] header), and on a pyproject.toml that configures a locking dependency manager ([tool.poetry], [tool.pdm] or [tool.uv]), declares at least one dependency besides python, and has no uv.lock, poetry.lock, pdm.lock, Pipfile.lock or pylock.toml in its directory. A uv.lock in an enclosing directory counts, so uv workspace members are not reported.
Not flagged: a setuptools, flit or hatch pyproject.toml with no locking tool configured (a library publishes ranges by design), a project with no dependencies, requirements.txt, and test fixtures.
# FLAGGED: pyproject.toml, no poetry.lock next to it
[tool.poetry]
name = "orders-api"
[tool.poetry.dependencies]
python = "^3.11"
fastapi = "^0.110"
# FLAGGED: Pipfile present, no Pipfile.lock
$ ls
Pipfile app.py
# (Pipfile.lock is missing)
Remediation
- Choose a lock-file-aware tool and generate the lock file. All three major Python packaging tools support lock files:
# uv (recommended — fast, hash-verified)
uv lock
uv sync
# Poetry
poetry lock
poetry install
# Pipenv
pipenv lock
pipenv install
- Commit the lock file to version control. The lock file must be tracked in source control so every environment — developer laptops, CI runners, production containers — installs exactly the same dependency graph.
git add uv.lock # or poetry.lock / Pipfile.lock
git commit -m "chore: add Python lock file"
- Install from the lock file in CI/CD. Use commands that refuse to deviate from the recorded versions:
# uv — strict mode honours the lock file exactly
uv sync --frozen
# pip with hash verification (works with requirements.txt exported from uv/poetry)
pip install -r requirements.txt --require-hashes
Audit the lock file regularly. Lock files freeze versions, but those versions may still receive CVEs over time. Pair lock-file discipline with a dependency scanning tool and re-run
uv lock --upgrade-package <pkg>orpoetry updatewhen patches are released.Never gitignore lock files. Check that
uv.lock,poetry.lock, andPipfile.lockare not listed in.gitignore. These files are intentionally committed even for applications (as opposed to libraries, where policy differs).
# SAFE: install exactly what the lock file specifies with hash verification
uv sync --frozen
References
- CWE-829: Inclusion of Functionality from Untrusted Control Sphere
- OWASP Software Component Verification Standard
- uv documentation – Lock files
- Poetry documentation – poetry.lock
- Pipenv documentation – Pipfile.lock
- MITRE ATT&CK T1195.001 – Supply Chain Compromise: Compromise Software Dependencies
- CAPEC-185: Malicious Software Download