How to keep a capped dependency from blocking Dependabot security updates
Need Dependabot to skip a package’s routine bumps while its security fixes keep arriving? That is a different fix: how to ignore a dependency in Dependabot without blocking its security updates.
A version ceiling in pyproject.toml looks like a way to hold Dependabot inside a known-good range. It does not work that way, and which way it fails depends on versioning-strategy. Under the default strategy Dependabot rewrites the ceiling. Under lockfile-only it opens no pull request and logs security_update_not_possible, which is the failure this page fixes.
Prerequisites
- A uv project with
uv.lockcommitted. - Dependabot security updates enabled under Settings → Advanced Security. That setting is what opens security pull requests;
dependabot.ymlonly narrows them. - A
.github/dependabot.ymlfor theuvecosystem. The examples uselockfile-only, the strategy that turns a cap into a silent failure:
version: 2
updates:
- package-ecosystem: "uv"
directory: "/"
schedule:
interval: "weekly"
versioning-strategy: lockfile-onlyDrop the cap or raise it
Remove the ceiling and let uv.lock hold the exact version. The lockfile is what makes the environment reproducible, so the manifest range does not need to be tight:
[project]
dependencies = ["requests>=2.31.0"]Keep the cap only when an upper bound is a real compatibility fact, such as a package that breaks against the next major release. Then raise the ceiling manually whenever an advisory lands above it.
The rest of this page covers what the cap does while it is still there.
Expect the default strategy to rewrite the ceiling
The default versioning-strategy is auto, which applies increase to applications and widen to libraries. increase-if-necessary leaves a constraint alone only while it already admits the new version, so it edits a cap too. Every strategy except lockfile-only rewrites the constraint rather than respecting it. A security update against requests>=2.31.0,<2.32 in an application moved both bounds:
- "requests>=2.31.0,<2.32",
+ "requests>=2.33.0,<2.34",
The routine version update on the same project did the same thing, landing on >=2.34.2,<2.35. Both paths keep the shape of the constraint and slide it upward, so the ceiling never blocks anything it was written to block.
Expect lockfile-only to fail silently
Setting versioning-strategy: lockfile-only stops the rewrite and replaces it with silence, because the strategy forbids Dependabot from editing the manifest at all. On an identical capped project, Dependabot opened no pull request and failed the job. The evidence is in the job log: open Insights → Dependency graph → Dependabot, click Recent update jobs beside the manifest, then view logs on the security run:
INFO Requirements to unlock update_not_possible
INFO The latest possible version of requests that can be installed is 2.33.0
INFO The earliest fixed version is 2.33.0.
| security_update_not_possible |
The alert reads “Dependabot cannot update requests to a non-vulnerable version” and never mentions the ceiling that caused it. The same project without the cap got its security pull request.
To catch the vulnerable version without depending on Dependabot’s job status, run uv audit in CI. It reads uv.lock against the OSV database and fails the build until the fix lands, cap or no cap.
Read a doubled alert count as the symptom
A capped manifest raises a second set of alerts against pyproject.toml on top of the uv.lock ones, so one vulnerable package in a capped project produced six alerts where an uncapped one produced three.
An alert count that jumps for one package without a new advisory is worth checking against a declared range that cannot admit the fixed version.