Safeguard
Security Guides•

Which Dockerfile step added the vulnerable package in my image?

Trace a scan finding to the build step that added it with image history and layer size, then decide whether the fix is in your Dockerfile or the base.

Safeguard Security Team
4 min read

To find which Dockerfile step added a vulnerable package, list the image history, match the layer that added the package by its command and size, then check whether that step is yours or came from the base image. Steps from the base image are fixed by changing the base. Steps from your Dockerfile are fixed in your file.

Start with the history

The docker image history command shows how an image was built: one row per layer with the command that created it, its size and a comment. The Docker reference says the output can be given in full with the no truncate option, which you need because the create command is cut short by default.

docker history --no-trunc --format 'table {{.CreatedBy}}\t{{.Size}}' myapp@sha256:abc123

Read from the bottom. The lowest rows are the base image's own steps, and the top rows are your Dockerfile steps in reverse order.

Match the package to a row

  1. Note the package name from the finding. If your scanner reports a layer digest, use it.
  2. Find the row whose command installs it. A package install command naming the package is the obvious match.
  3. If no row names it, the package arrived as a dependency of something else, or it was already in the base. Look at large rows near the bottom.
What you seeMeaningFix lives in
Install command in a top row naming the packageYou installed itYour Dockerfile
Install command naming a different packagePulled in as a dependencyRemove the parent or pin differently
Row from the base's own stepsInheritedThe base image or its tag
No row matchesPossibly a copied file or a compiled artifactYour build output

Limits of history

History records commands, not file lists, and a base image built elsewhere may show few or no commands. Multi-stage builds also drop earlier stages, so the final image's history shows just the last stage. If you need file level detail, a scanner or SBOM that records the layer for each package is more precise. The OCI specification describes layers as filesystem changesets applied in order, so each package file belongs to one layer in the sequence. See what a container image layer is.

Remember that history can also show what you built with. Commands and arguments are visible to anyone who can pull the image, which matters for secrets. See Docker history explained.

After you know the step

  • Your step: update, pin or remove the package, then rebuild. See remove or patch.
  • Base step: bump the base tag with a fresh pull. See fix base findings first.
  • Unclear: ask for an SBOM from the build, which lists packages with their sources.

Record the answer in the ticket so the next engineer does not repeat the trace.

Where Safeguard fits

Safeguard's SBOM and dependency scanning lists components per image so you can match a finding to its origin, and policies can require an approved base. Free scan: gold.safeguard.sh/scan.

Try it yourself

Click through it at your own pace, or open it full screen. Look for where each package came from.

Quick check

Why is the command text cut off in the history output?

By default long commands are truncated. Use the no truncate option to see the full text.

Does history work on a multi-stage image?

It shows the final stage alone. Earlier stages are not part of the shipped image.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.