Usually the best move is the smallest upgrade that includes the fix, not the newest version available. A patch or minor upgrade is cheaper and less likely to break your app. Jump to the latest only when the fix needs it, or when you are already overdue. Test every change before you ship.
TL;DR
- A fixed version is the first release that repairs the flaw. That is your target.
- Version numbers have three parts: major, minor, patch. They hint at how risky an upgrade is.
- Patch upgrades are usually safe. Minor upgrades are usually safe. Major upgrades can break your code.
- Numbers are a promise made by the package author, not a guarantee. Test anyway.
- Staying many versions behind makes the next fix harder, so do not delay forever.
What do the numbers in a version actually mean?
Definition: Semantic versioning, often called SemVer, is a common way to number software releases as MAJOR.MINOR.PATCH, such as 4.17.21. Each part signals what kind of change happened since the last release.
The official SemVer specification puts it this way. Increase the patch number for backward compatible bug fixes. Increase the minor number when you add functionality in a backward compatible way. Increase the major number when you make incompatible changes. In plain words:
| Part | Example change | What it means for you |
|---|---|---|
| Patch (4.17.20 to 4.17.21) | A bug fix | Should be a drop in replacement |
| Minor (4.17.21 to 4.18.0) | A new feature, nothing removed | Should still work with your code |
| Major (4.18.0 to 5.0.0) | Something was removed or changed | Your code may need edits |
Think of a car. A patch is like fixing a faulty brake light bulb. A minor update is like adding a new cup holder. A major update is like switching from a manual to an automatic gearbox: the car still drives, but you now have to learn it again.
One more rule from the spec is useful for security work. Once a version has been released, its contents must not be changed. Any fix has to be published as a new version. That is why the scan report names a specific fixed version for you to move to.
Why not always take the latest version?
Because newer is not always smaller or safer for you. Three reasons.
- More change means more risk of breakage. The latest version may include several major jumps your code has never met.
- The fix may be available much earlier. If the flaw was repaired in 4.17.21 and the latest is 6.2.0, you can take the small step first.
- You can test one change at a time. If something breaks after a small upgrade, you know exactly where to look.
There is a catch. The SemVer spec says version zero, anything numbered 0.y.z, is for initial development, and anything may change at any time. So if your package is still on a 0.something version, treat even small upgrades with care.
Another catch is trust. The numbers are the author's promise. Authors sometimes label a change as a patch when it actually changes behavior. That is why testing is not optional. The OWASP Top 10 lists, among the ways you become vulnerable, not testing the compatibility of updated, upgraded, or patched libraries.
When is the latest version the right answer?
Sometimes you should go further than the minimum. Choose the newest release when:
- The fixed version is itself old and no longer receiving fixes, and the newest line is the only one supported.
- Several findings in the same package are all fixed only in the newest line.
- You have been ignoring updates for a long time, and going step by step would cost more than one planned jump.
- The package author states that older lines are end of life.
The OWASP guidance also says to monitor for libraries that are unmaintained or do not create security patches for older versions. If the older line gets no fixes, staying on it is the risk.
How do I decide, step by step?
- Find the fixed version in your scan report. Write down the current version and the fixed version.
- Compare the numbers. Is the jump patch, minor, or major?
- Read the release notes. For minor and major jumps, look for a section on breaking changes.
- Check how many places use the package. More use means more testing.
- Upgrade on a branch. Do one package, or one small group, at a time.
- Run your tests. If you have few tests, click through the main flows by hand.
- Ship and rescan. Confirm the finding is gone.
- If it breaks, step back to the smallest fixed version, or plan the larger change as its own task.
The npm documentation adds a useful warning about automatic fixes. Its audit command can apply remediations with a fix option, but it notes that some vulnerabilities cannot be fixed automatically and will require manual intervention or review. Treat automatic fixes as a helpful draft, not a final answer.
A worked example with invented numbers
The versions below are invented for teaching.
Your scan shows that package "formatter" at version 3.4.1 has a high severity flaw. The report says the fix is in 3.4.5. The newest release is 5.1.0.
- Option A: move to 3.4.5. That is a patch jump. Risk of breakage is low. Time: maybe 30 minutes including tests.
- Option B: move to 5.1.0. That is a major jump of two numbers. Release notes list three removed settings your app uses. Time: maybe two days.
Take option A today. The flaw is closed, and you ship the same afternoon. Then create a separate task for option B, with a due date, because staying on version 3 will not stay supported forever. You have split an urgent job from a planned job. That split is the main skill in dependency upgrades.
Now imagine a second finding where the only fixed version is 5.0.2, which is a major jump. In that case you have no small step. You schedule it, give it an owner, and look at whether a workaround is possible in the meantime. Our post on deciding severity when you know very little can help you judge urgency, and the CVSS, EPSS and KEV FAQ explains signals that raise or lower priority.
What if the vulnerable package is not one I installed?
Then it is a transitive dependency, pulled in by another package. You often cannot upgrade it directly. The usual path is to upgrade the package that needs it, since a newer version of that parent may already use the fixed child. See direct versus transitive dependencies for the full picture.
Try it yourself
The demo below shows fixes available now in a sample workspace. Click through and look for how upgrades are grouped into compatible, minor, and major, and how the ones that may break your code are marked.
Click through it at your own pace, or open it full screen.
Quick check
Is a patch upgrade always safe?
It should be, if the author followed the SemVer rules, but it is a promise rather than a guarantee. Run your tests after every upgrade, even a small one.
What if the fixed version is a major upgrade?
Plan it as a real task. Read the release notes, give it an owner and a date, and look for a temporary workaround or a mitigation while you prepare.
Should I upgrade everything at once to save time?
Usually no. Small batches are easier to test and easier to undo. Group changes by risk: patches together, minor upgrades together, and major upgrades one at a time.
What does 0.x mean in a version number?
The SemVer spec says major version zero is for initial development, and anything may change at any time. Be extra careful with upgrades in that range.
How can Safeguard help with this?
Safeguard's dependency scanning shows the fixed version for each finding. Autonomous remediation can open a fix pull request for you. It is off by default, and every category starts on Manual, so nothing changes in your code until a person approves it. Policies and gates can then stop a pull request that would bring in a known bad version.
The Safeguard CLI can also write code, for example to draft the edits for an upgrade, and you review that change the way you would review any teammate's work. You can try a free scan at gold.safeguard.sh/scan.
Sources
- Semantic Versioning 2.0.0
- npm Docs: npm audit
- OWASP Top 10 2021, A06 Vulnerable and Outdated Components (source text on GitHub)
Last reviewed: 19 October 2026.