With pip-tools, run pip-compile with the upgrade-package option naming only the vulnerable package, optionally with a version constraint. Existing pins stay in place, and only that package and what it requires change. Then review the diff, run your tests, and sync the environment. This keeps a security fix from turning into a full upgrade.
Why partial upgrades matter in analytics projects
Data projects are sensitive to version changes. A new pandas or numpy release can change numeric output, and reports built on it may shift. Teams therefore put off upgrades, and advisories pile up.
A targeted bump lets you fix a single flagged package, with a small diff that a reviewer can read.
How pip-compile behaves
From the pip-tools documentation: pip-compile builds a pinned requirements file from requirements.in, pyproject.toml, setup.cfg or setup.py. The output pins each package, including indirect ones, and annotates where each came from. If an existing output already satisfies your inputs, pip-compile leaves it unchanged, even when newer versions exist. When new inputs conflict with pins, it updates the pins and prints a warning.
To refresh, there are two options. The upgrade flag refreshes all packages. The upgrade-package flag, with the short form -P, refreshes only named packages, optionally with a constraint.
pip-compile --upgrade-package requests
pip-compile --upgrade --upgrade-package 'requests<3.0'
The steps
- Find the fixed version in the advisory.
- If the package is a direct dependency, set a minimum in
requirements.in. If it is transitive, you can name it with the upgrade-package flag and a lower bound. - Run pip-compile with that flag in the project's virtual environment, so environment markers resolve correctly.
- Read the diff of the output file. Expect the named package and perhaps a few of its dependencies, and nothing else.
- Run the tests and one representative report, comparing outputs.
- Apply with
pip-sync, but note the pip-tools warning: pip-sync is meant to be used only with a requirements file generated by pip-compile. - Merge, deploy and re-scan to confirm the advisory no longer applies.
If the diff is bigger than expected
| Symptom | Likely cause |
|---|---|
| Many packages changed | Another package required a newer shared dependency, so read the annotations |
| Resolver warning about discarded pins | A conflict between your inputs and existing pins |
| Package did not move | A constraint in your inputs holds it back, so loosen it deliberately |
If the fix needs a major version jump, schedule it as a proper upgrade rather than hiding it in a security patch.
Hashes
pip-tools can add hashes with the generate-hashes flag. The documentation only says this supports pip's hash checking mode, so see the existing Python hash generation guide for what that protects.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how a fixed version is surfaced next to the vulnerable one.
Where Safeguard fits
Safeguard's dependency scanning identifies vulnerable pins, and autonomous remediation can open fix pull requests; it is off by default, with every category set to Manual. Start with a free scan.
Quick check
Does pip-compile upgrade everything by default?
No. Existing pins stay put unless you ask for an upgrade.
Is pip-sync safe to run on any requirements file?
The pip-tools docs say to use it only with a file generated by pip-compile.
Sources
Last reviewed: 19 October 2026.