A container scan can report a deleted package because images are stacked layers. Deleting a file in a later step only hides it with a marker, and the bytes still ship in the earlier layer. Some scanners read every layer. The cleaner fix is a build where the file never enters a layer.
How layers work
An OCI image is a stack of filesystem layers. The OCI image specification describes each layer as a changeset: a tar archive containing only what was added or modified, with deleted files or directories marked by whiteout entries. Applying the stack in order gives the final filesystem you see when the container runs.
So when a Dockerfile step installs a package and a later step removes it, the result is two layers:
layer 3: adds package files
layer 4: whiteout markers for those files
The running container shows no package. But layer 3 is still part of the image, and anyone who pulls it receives that layer.
Why scanners may still flag it
Scanners differ in what they inspect:
| Approach | Sees deleted package? | Notes |
|---|---|---|
| Final merged filesystem only | No | Matches what runs |
| Every layer separately | Yes | Matches what ships |
| Package database in final image | Depends | Database may keep stale entries |
A finding from a lower layer is not a false positive in the strict sense. The vulnerable files are present in the artifact. But whether it matters at runtime is another question, because the files are not visible in the final filesystem.
What to do about it
- Check the layer. Identify which layer the finding came from.
- Decide if it matters. If secrets or code were in that layer, deletion does not protect them. For a vulnerable library no longer used, the runtime risk is low, but it still ships.
- Fix the build, not the scan. Use a multi-stage build so build tools stay in an earlier stage that is never part of the final image.
- Combine steps. Install and clean in a single step so the intermediate files are never recorded in a layer.
- Rebuild and rescan. Confirm the finding is gone.
A multi-stage build looks like this in outline:
stage 1: build, with compilers and dev packages
stage 2: start from a minimal base, copy only the built output
Only stage 2 becomes the shipped image. Build tools never appear, so they cannot be reported.
The package database wrinkle
Operating system package managers keep a database of what is installed. If a package was removed by deleting files rather than through the package manager, the database may still list it. Scanners that read that database then report a package that is not really there. Using the package manager's own removal command keeps the record honest.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at how findings are attributed to image components, then think about which layer each would come from.
Where Safeguard fits
Safeguard's SBOM and dependency scanning builds an inventory you can compare with what an image should contain, and gates can block a pull request on findings. The free scan is a quick way to see what an image contains.
Quick check
Is a finding in a deleted file a false positive?
Not strictly. The files ship in the layer. It may have little runtime effect, but the cleaner answer is to rebuild so they never enter the image.
Does deleting a secret in a later layer protect it?
No. The earlier layer still holds it, and anyone with the image can extract that layer.
Sources
Last reviewed: 19 October 2026.