Try a constraint first. In uv, constraints can only reduce the set of acceptable versions, which is enough when you want a floor on a vulnerable package. Use an override when a parent declares an upper bound that blocks the fixed release, because overrides replace declared requirements and can expand the allowed range.
The difference in one table
| Feature | Setting | What it can do |
|---|---|---|
| Constraint | constraint-dependencies in the tool.uv table | Narrow acceptable versions |
| Override | override-dependencies in the tool.uv table | Replace declared requirements, narrow or widen |
| Exclude | exclude-dependencies in the tool.uv table | Remove a dependency from resolution |
The uv documentation spells out the key line: constraints can only reduce the set of acceptable versions for a package, while overrides can expand the set, providing an escape hatch for erroneous upper version bounds. As with constraints, a global override does not add a dependency on the package. It only takes effect if the package is requested directly or transitively.
When a constraint is enough
Say the advisory says versions below 3.1.4 are affected and no parent forbids newer ones. Add a constraint that sets the floor at 3.1.4. uv resolves, and the transitive package moves up. Nothing else about your dependency declarations changes, and the constraint documents your intent.
When you need an override
Suppose a parent package declares a requirement such as a library below version 2, but the fixed release is 2.1 and the parent works fine with it. A constraint cannot help, since it only narrows. The docs give an example of exactly this shape: a transitive dependency declares a range that excludes the newer major version, yet it works with it, so you override the declared requirement with a wider one. uv then ignores all declared requirements on that package and uses the override.
Overrides can also be scoped. The docs show an inline table that targets the dependencies of one parent package and version, so the replacement applies only under that parent. Scope it whenever you can. A global override silences every declared requirement on that package, including ones you might later want to respect.
Risks of overriding
An override is you telling the resolver to trust a combination the parent's author did not test. Treat that seriously.
- Read the parent's changelog for the child's newer major version.
- Run the parent's own usage paths in your tests, not only unit tests.
- Leave a comment in the file naming the advisory and the date.
- Add a calendar reminder to remove the override once the parent releases a compatible range.
Overrides rot quietly. If you never revisit them, they hide the next conflict and stay in the file long after the upstream has caught up.
Try it yourself
Click through it at your own pace, or open it full screen. Check whether the flagged code path is reachable before you decide how hard to push an override.
Where Safeguard fits
Safeguard scans dependencies, runs reachability analysis to show which findings your code can actually reach, and can open fix pull requests through autonomous remediation. That last feature is off by default and every category starts on Manual, so a person approves each change. You can try a free scan on a repository first.
Quick check
Can a uv constraint raise a package above a parent's upper bound?
No. Constraints only narrow the allowed set, so a parent's upper bound still wins. Use a scoped override.
Does an override add the package to my project?
No. A global override takes effect only if the package is already requested directly or transitively.
Sources
Last reviewed: 19 October 2026.