A fixed vulnerability usually reappears because the fix did not reach everywhere the flawed software lives: an old copy in another project, a stale build, an indirect package pulling the old version back, or a scan reading outdated data. Find which place still holds the old version, then fix that place.
TL;DR
- Reappearing findings are usually real, not scanner mistakes.
- Check six places: other projects, old images, indirect packages, lock files, caches, and merge conflicts that undid your change.
- Rescan the exact thing that was deployed, not just the code on your laptop.
- Add a check that blocks the old version from coming back.
Why does this happen so often?
Software is copied in many places. The same package can sit in your main app, a helper tool, a test setup, a container image and a backup branch. Fixing one copy leaves the others. A scanner reads every place it is pointed at, so it keeps reporting the ones you missed.
Think of a leaking pipe. You fix the one under the kitchen sink. The inspector returns and finds the same type of leak under the bathroom sink, because the same builder used the same pipe in both. The inspector is not wrong, and neither were you. The fix just did not cover every room.
A few terms first. A vulnerability is a flaw someone could misuse. A dependency is a package your code relies on. An indirect dependency, also called a transitive dependency, is a package that one of your dependencies relies on. You did not choose it directly, but you still ship it.
What are the six usual causes?
| Cause | What is happening | How to check |
|---|---|---|
| Another project uses it | The fix was made in one repository only | Search all repositories for the package name |
| Old container image | The deployed image was built before the fix | Check the build date and rebuild |
| Indirect package | Another package keeps asking for the old version | Look at the dependency tree for who requires it |
| Lock file not updated | The file that pins exact versions still lists the old one | Regenerate the lock file and commit it |
| Cache or stale build | The build tool reused an old copy | Clear caches and rebuild from clean |
| Change was undone | A merge or a revert brought the old version back | Review recent history for the file |
Cause 1: another project uses the same package
This is the most common one in teams with several repositories. Search every repository you own for the package name, not just the one where the alert fired. A written list of software, as described in how to start vulnerability management, makes this search quick.
Cause 2: the running image is older than the fix
A container image is a packaged copy of an application and everything it needs to run. Images are built at a moment in time. If you fixed the code but never rebuilt and redeployed the image, the running version still has the flaw. Scan the image that is actually running, and compare its build date with the date of your fix.
Cause 3: an indirect package keeps pulling in the old version
You upgrade the package you control, but another package you use still asks for the old version of the vulnerable one. The package manager may pick the old one. To see which package asks for it, view your dependency tree. Then either upgrade the outer package, or use your tool's setting that forces a specific version, often called an override or resolution. Test after forcing, because the outer package may not like the change.
Cause 4: the lock file still lists the old version
Many tools write a lock file, a file that records the exact version of every package so builds repeat exactly. If you edit the main settings file but do not refresh the lock file, the build still installs the old version. Regenerate the lock file and commit it with the change.
Cause 5: caches and stale builds
Build systems cache downloads to save time. A cache can serve an old copy. Clear it and rebuild from a clean state, then scan the new output.
Cause 6: someone undid the fix
A merge from an older branch, an automated update that downgrades a version, or a revert can quietly restore the old package. Check the recent history of the file that sets the version.
How do you find the cause quickly?
Ask these questions in order.
- Is the new finding in the same place as the old one? If not, it is a different copy. Go to cause 1.
- Does the scan target the deployed artifact or only source code? If it scans an image, check cause 2.
- Does the dependency tree show the package pulled by something else? That is cause 3.
- Does the lock file list the old version? That is cause 4.
- Does a clean rebuild change the answer? If yes, it was cause 5.
- Does the history show a revert? That is cause 6.
A worked example with invented numbers
These numbers are invented to show the process, not drawn from a real case.
On Monday you upgrade a package from 1.2.0 to 1.2.4 to remove a flaw in the web app. The scan clears. On Friday the weekly scan shows the flaw again, with 3 findings.
| Finding | Where | Cause |
|---|---|---|
| 1 | Billing service repository | Cause 1: never upgraded |
| 2 | Production image, built last Tuesday | Cause 2: image older than the fix |
| 3 | Web app, via a reporting plugin | Cause 3: the plugin requires 1.2.0 |
You upgrade the billing service, rebuild and redeploy the image, and update the reporting plugin to a newer release that accepts 1.2.4. Three findings, three different causes, one root issue: the fix was applied in one place only. After the rescan, the count is zero.
How do you stop it from coming back?
- Scan on every change. A rescan on each pull request catches a downgrade before it ships. Read about continuous vulnerability management.
- Set a rule. Use a policy that blocks a build when it contains a version known to be vulnerable.
- Scan what you deploy. Include built images and not only source code.
- Keep one inventory. One shared list of where each package is used turns step one into a search instead of a hunt.
- Record each fix. Write down which repositories and images were updated.
If you want to know whether a repeat finding might be a false alarm, see the false positives FAQ. A repeat finding is more often real than not, but a mismatch is possible, for example when a package was fixed in a way the database does not recognize.
Try it yourself
Click through it at your own pace, or open it full screen. Look for how repeated scans catch a version that comes back after it was fixed.
How can Safeguard help?
Safeguard scans dependencies and builds SBOMs for your projects, so the question of where else a package lives can be answered from one place. Policies and gates can block a pull request that reintroduces a known flaw. Because scans can run on each change, a version that returns is caught on the next run and not weeks later. You can see what a scan looks like with the free scan at gold.safeguard.sh/scan.
Quick check
Is a reappearing finding a scanner bug?
Rarely. Most of the time another copy, an old image or an indirect package still has the old version. Check those first.
What is a lock file and why does it matter?
It records the exact version of every package so that builds repeat exactly. If it is not updated, the build can still install the old vulnerable version.
How do I know which package pulls in the old version?
Look at your dependency tree. Most package tools can print it and show which package requires the vulnerable one.
Should I scan the code or the deployed image?
Both. Code shows what you intend to ship. The image shows what is actually running.
Last reviewed: 19 October 2026.