You fix a vulnerability in a container base image by rebuilding, not by patching the running container. Find out which findings come from the image in your FROM line, move that line to a fresher digest, a newer tag or a smaller base, rebuild without stale cache, and let a Safeguard scan in CI prove the count went down before you promote. Container image scanning is part of Safeguard SCA, which is GA.
This post is about the fixing half of the job. If you want the scanning half first, the published post on scanning container images in Safeguard covers how Safeguard reads image layers and gets images scanned. Here we assume you already have a long list of OS package CVEs and need to make it shorter in a way that stays short.
Key takeaways
- Base image fixes are rebuilds. NIST SP 800-190 says container updates "must be made upstream in the images themselves, which are then redeployed". Running a package upgrade inside a live container does not fix the image.
- Split the findings first. Scan the exact base reference from your
FROMline on its own and compare it with your built image. Findings in both belong to the base owner. Findings only in your image belong to your Dockerfile or your application. Container image scanning is part of SCA (GA). - Four fixes cover almost every base image finding. Rebuild against the current digest of the same tag, move to a newer tag, move to a newer distribution release, or move to a smaller base. Pick the smallest change that clears the findings you care about.
- Prove each fix with a scan. The Safeguard CLI (GA) scans a local image before you push. The CI step (GA) scans the image your pipeline built, records one version per environment and tag, and can fail the build with
--wait --fail-on. Policies and gates (GA) decide what may be promoted. - Keep it fixed. A registry integration (part of ESSCM, GA) keeps the image under continuous scanning, so a new CVE in a base you fixed last month shows up without anyone remembering to rescan. Vulnerability management with EPSS and CISA KEV (GA) tells you which new findings need a rebuild this week.
- Application dependencies are fixed in the repository. Autonomous remediation (GA) can open fix pull requests for them. It ships switched off, with every category set to Manual.
- Self-healing containers is generally available. Safeguard's docs describe a detect, plan, rebuild and promote loop with an advisory mode and autonomous modes. Run the manual process in this post first, then start it in advisory mode.
- Choose bases with evidence. Gold Open Source (GA, free, no login) has a Container Images directory at gold.safeguard.sh/directory/images, and its CVE pages show affected and fixed versions. Shortlist there, then scan your candidates with Safeguard before you switch.
Why base image vulnerabilities need a different fix
Application fixes follow one pattern: bump a version in a manifest, update the lockfile, merge. Base image findings do not, for three reasons.
You did not choose most of the packages. A general purpose base image carries a C library, a TLS library, compression libraries, certificate bundles, a shell, core utilities and a package manager. Your service may use three of them. Every one of them can carry a CVE, and every one of them shows up in your scan.
The fix is published by someone else, on their schedule. The distribution patches the package. The image publisher rebuilds the base image tag with the patched package. Only then can you rebuild on it. You control the last step, not the first two.
The image is frozen at build time. Once an image is built, nothing inside it changes. NIST SP 800-190, the Application Container Security Guide, puts it plainly in section 3.1.1: an image built with fully up to date components may be clean for days or weeks, but at some point vulnerabilities will be found in its components and it will no longer be up to date. Unlike servers patched in place, the guide says, container updates must be made in the images themselves, which are then redeployed.
That last point is the whole method. The unit of fixing is the image build, and the unit of deployment is the image digest. Everything in this post is about making that rebuild cheap, safe and provable.
What the standards ask for
You do not need a regulation to tell you to patch, but it helps to know which documents your auditors and customers will cite.
| Source | What it says about image fixes | How it shapes your process |
|---|---|---|
| NIST SP 800-190, section 3.1.1 | Images go stale as new CVEs are found; updates are made in the image and redeployed | Rebuild and redeploy is the fix, not in place patching |
| NIST SP 800-190, section 4.1.1 | Tools need visibility into all layers, not just the base, and quality gates at each stage | Scan base and app layers, gate promotion |
| NIST SP 800-190, section 4.1.2 | Use base layers from trusted sources only, update base layers frequently, prefer minimal bases | Choose bases deliberately and rebuild on a schedule |
| NIST SP 800-190, section 4.2.2 | Prune stale images from registries and deploy immutable, versioned names | Retire old images and pin what you deploy |
| NIST SP 800-218 (SSDF) | Practices for using well secured third party components and responding to vulnerabilities | Treat the base image as a third party component with an owner |
| CISA KEV catalog | Lists vulnerabilities known to be exploited in the wild | Rebuild first for KEV listed findings |
| FIRST EPSS | Estimates the probability that a CVE will be exploited | Rank the rest of the queue |
| CISA BOD 26-04 (10 June 2026) | Risk based timelines for federal agencies; it superseded BOD 22-01 | If you sell to US federal agencies, map your rebuild cadence to it |
BOD 22-01 and its fixed deadlines are history; BOD 26-04 replaced them with risk based timelines. None of these documents name a base image. They tell you to know what is in it, keep it current and prove both.
How image layers decide who owns a fix
The OCI image specification describes an image manifest as an ordered list of layers, with the base layer first. Each later layer is a change set applied on top. Your Dockerfile maps onto that list:
- The
FROMline brings in every layer of the base image. - Each
RUN,COPYorADDinstruction adds a layer on top. - In a multi-stage build, only the final stage's layers end up in the image you ship. Docker's multi-stage build documentation describes using several
FROMstatements and copying only the artifacts you need into the last stage.
That structure tells you who owns each finding:
| Where the vulnerable package came from | Typical examples | Who usually owns the fix | The fix |
|---|---|---|---|
| The base image | C library, TLS library, compression libraries, certificate bundle, shell utilities | Platform team or base image owner | Rebuild on a fresh digest, a newer tag, a newer distribution release or a smaller base |
| An OS package your Dockerfile installs | A download tool, an image processing library, a database client | The service team | Remove it, move it to a build stage, or upgrade it in the same RUN line |
| An application dependency | npm, PyPI, Maven, Go, Cargo, NuGet, Composer or Bundler packages | The service team | Fix the manifest and lockfile in the repository, then rebuild |
| A compiled binary copied in | A Go or Rust binary, a vendored tool | Whoever builds that binary | Rebuild the binary with fixed dependencies |
Safeguard's container FAQ lists what it scans in an image: OS packages from apt, yum and apk, application dependencies, and compiled Go and Rust binaries. That covers every row in the table. What the scan does not do for you is decide whose row a finding belongs to. That is the next section.
Step 1: split base image findings from your own
Before you change anything, find out how many of your findings you can clear by changing one line. This uses only documented commands.
-
Find the exact base reference. Read the
FROMline of the final stage of your Dockerfile. If it names a tag, look up the digest that tag pointed to when your image was built. Safeguard's container FAQ supports both tag references such asnginx:1.21and digest references such asnginx@sha256:..., and recommends digests for production scanning because a digest always names the same image. -
Scan the base image on its own. From the Safeguard CLI (GA):
safeguard scan --image node@sha256:<digest-from-your-build>Or connect the base image in the app under Integrations as a public or private container image, so it is scanned continuously in its own right. The FAQ's flow for a public image is: go to Integrations, select Container Image, choose the Public tab, enter the image reference and click Connect.
-
Scan your built image. Either locally, as the FAQ shows:
docker build -t myapp:test . safeguard scan --image myapp:testor in CI, with the step described later in this post.
-
Compare the two results. A finding on the same package and version in both scans is inherited from the base. A finding that appears only in your image came from your own layers.
-
Cross check the leftovers with your repository scan. If a package and version in your image also appears in your repository's SCA results, it is an application dependency with a lockfile to fix. If it appears only in the image, it came from an OS package you installed or a binary you copied in.
The container FAQ explains why an image shows more vulnerabilities than its source code: base OS packages, build dependencies, system libraries and outdated base images. The comparison turns "we have a lot of findings" into "one line in our Dockerfile owns most of them", which is an easier conversation with whoever owns that line.
Rank before you rebuild
Not every base image finding needs a rebuild today. Safeguard's vulnerability management (GA) attaches CVSS, EPSS and CISA KEV status to each finding and groups findings as Critical, High, Medium, Low and Exploitable. Use that to decide urgency:
- KEV listed, fix available in a newer base: rebuild now. CISA's catalog exists for exactly this case.
- High EPSS, fix available: rebuild in the current cycle.
- Low EPSS, fix available: let the scheduled rebuild pick it up.
- No fix available yet: record an exception with an expiry date and watch for the fixed revision.
Reachability analysis (GA) ranks application dependency findings by whether your code calls the vulnerable path. The published post on prioritising vulnerabilities with reachability, EPSS and KEV explains how those signals combine. Safeguard's reachability docs list support by programming language, not by OS package manager, so rank inherited OS packages by KEV, EPSS and whether your process actually uses the package.
Step 2: pick the smallest base change that clears the findings
There are four ways to change a base image. They differ in how much can break and how many findings they clear.
Fix A: the same tag, a newer digest
Base image publishers rebuild their tags when the distribution ships patched packages. A tag such as 20-alpine or bookworm-slim keeps its name while the image behind it changes. If your last build pulled that tag three weeks ago, a fresh pull today may already contain the fixes.
What to do:
- Rebuild with a fresh pull of the base and without the layer cache. Docker's build best practices page has sections titled "Rebuild your images often", "Use --pull to get fresh base images" and "Use --no-cache for clean builds" for this reason. A cached build can happily reuse a three week old base layer.
- If you pin by digest, which you should, update the digest in your
FROMline to the one the tag points to now. - Scan the new base digest on its own with
safeguard scan --imageand compare it with the old one before you rebuild your service on it.
Risk: low. The distribution's stable branch changes as little as possible between revisions. Debian's security FAQ explains that it backports security fixes into the version shipped in a stable release instead of moving to a new upstream version, so that "things will not change or break unexpectedly". The same reasoning applies to most stable distribution branches.
Fix B: a newer tag in the same line
Sometimes the fix lives in a newer minor version of the runtime image, for example moving from one point release of a language runtime image to the next. The OS layer may stay the same while the runtime binaries change.
Update the tag and digest, rebuild and rerun your tests. Risk: moderate, since the runtime itself changes. Read its release notes.
Fix C: a newer distribution release
Distribution releases reach end of life. After that, packages in the old release stop getting security fixes, and every new CVE in them stays open forever. If your Safeguard scan shows a growing list of findings with no fixed version, and the base is on an old distribution release, the fix is a move to a supported release.
What to do: change the FROM line to the same runtime on the newer distribution, rebuild, and test anything that links against system libraries. Native extensions, database drivers and image processing libraries are the usual sources of breakage.
Risk: moderate to high. Plan it as a small migration with its own pull request and test run.
Fix D: a smaller base
If most of your findings sit in packages your service never uses, the most durable fix is to stop shipping those packages. Safeguard's container FAQ recommends minimal base images, gives Alpine and distroless as examples, and recommends official images where possible. NIST SP 800-190 section 4.1.2 makes the same point: select base layers from minimal technologies to reduce attack surface.
The distroless project describes its images as containing only an application and its runtime dependencies, without package managers or shells. Safeguard's FAQ confirms distroless images can be scanned and adds a fair warning: they have fewer packages but may still have vulnerabilities in the components they include.
What to do: use a multi-stage build. Compile or install in a full build stage, then copy only the artifacts into a minimal final stage. Rebuild and run your full test suite, including startup and health checks, because a missing shared library or certificate bundle only shows up at runtime.
Risk: highest of the four. Debugging changes too, since there may be no shell in the final image. The payoff is that the next six months of base image CVEs mostly never reach you.
Which fix to choose
| Your situation | Start with | Why |
|---|---|---|
| Findings have fixed versions and your base tag is current | Fix A, fresh digest | The publisher has probably already rebuilt the tag |
| The fixed version is only in a newer runtime release | Fix B, newer tag | The runtime binaries carry the fix |
| Findings pile up with no fixed version and the distribution release is old | Fix C, newer distribution release | The old release may no longer get fixes |
| Most findings are in packages your service never uses | Fix D, smaller base | Removes the packages instead of patching them |
| Findings appear only in your image, not in the base | Not a base fix | Edit your Dockerfile RUN lines or your lockfile |
| A KEV listed CVE has no fix in any base you could use | An exception with an expiry, plus compensating controls | Record the decision and revisit it on a date |
A useful rule: do Fix A on a schedule for every image. It keeps the gap between "the publisher fixed it" and "you shipped it" short, and turns Fix B, C and D into planned work.
Step 3: choose a base with Gold Open Source
When you need a new base, either for Fix C or Fix D or for a new service, start with evidence rather than habit. Gold Open Source is Safeguard's free public directory. It needs no login. The offering files list a Container Images directory alongside the Gold Certified Packages directory, and CVE intelligence with CVSS, EPSS, CISA KEV status and affected and fixed versions. Gold Open Source is GA.
What the Container Images page shows
The Container Images directory lives at gold.safeguard.sh/directory/images. It sits in the site's "Explore Gold" menu next to Packages, Gold Packages, AI Models, MCP Servers and Agent Skills. The page describes itself as a place to find Docker and OCI container images scanned for CVEs and license issues, with full vulnerability reports and verification status for production ready base images.
One honest caveat about this section. We read the page with a plain HTTP fetch while writing, and that returns the page shell and its description. The image list itself loads in your browser. So we are not going to describe columns, filters or counts we could not see. Open the page, look at what each listing shows for the images you are considering, and treat the listing as a starting point, not a verdict.
A shortlist method that works with any listing
- Write down your constraints first. Runtime and version, C library (glibc or musl), architecture, whether you need a shell or package manager at runtime, and how long the distribution release is supported.
- Shortlist two or three candidate bases from the Gold Container Images directory and from the runtime's official images.
- Look up your worst current CVEs on Gold Open Source. Its CVE pages show affected and fixed versions. If a candidate's package version falls in the fixed range, that candidate clears the finding. The published post on using Gold Open Source in your workflow covers the lookup, the free API and badges.
- Scan each candidate yourself. Run
safeguard scan --imageagainst each candidate by digest. This is the step that matters, because it uses the same scanner and data you will be judged by later. - Build your service on the best candidate in a branch. Scan the built image, run your tests, and compare the result with your current image.
- Record the decision. Note the candidate digests, the counts before and after, and why you chose the one you did. That record answers the auditor question "why this base?" without a meeting.
What to compare between candidates
| Question | Where to look | What good looks like |
|---|---|---|
| How many known CVEs does the candidate carry today? | safeguard scan --image on the candidate digest | Fewer, and few or none that are KEV listed |
| Are the remaining CVEs fixable? | Fixed version field in the scan; Gold Open Source CVE pages | Fixed versions exist, or the package is unused |
| How many packages does it ship? | The scan's SBOM for the candidate | Only what your service needs at runtime |
| Is the distribution release supported? | The distribution's own release and security pages | Supported well past your next planned migration |
| Does your service still work? | Your test suite against an image built on the candidate | Tests and startup checks pass |
| Is the reference pinned? | Your Dockerfile FROM line | A digest, with the tag kept as a comment for humans |
Step 4: rebuild and prove the fix in CI
Once you have chosen the change, make it in a pull request and let the pipeline prove it. This is the flow from Safeguard's CI/CD container images docs. The CLI and the CI step are GA.
-
Update the
FROMline. Change the tag, the digest or both. A digest pinned base keeps the build repeatable:# node 20 on Alpine, digest updated after rescan FROM node@sha256:<new-digest> -
Get a CI key. Create a key with
scans:triggerandscans:read. Admins create one in the Set up CI/CD sheet or under Settings › Developer. Store it in your CI asSAFEGUARD_API_KEY. -
Add the scan step after the build. The docs show this GitHub Actions example:
- name: Build run: docker build -t "ghcr.io/acme/api:${{ github.sha }}" . - name: Safeguard image scan (prod) env: SAFEGUARD_API_KEY: ${{ secrets.SAFEGUARD_API_KEY }} SAFEGUARD_INSTALL_DIR: ${{ runner.temp }}/safeguard-bin IMAGE: ghcr.io/acme/api:${{ github.sha }} run: | set -eu curl -fsSL https://cli.safeguard.sh/install | bash "$SAFEGUARD_INSTALL_DIR/safeguard" ci scan --image "$IMAGE" --environment prod --wait --fail-on criticalThe docs say the scan runs on the runner and only the results leave it. The image is read from the local Docker daemon when the step runs on the machine that built it, or from a registry using
SAFEGUARD_REGISTRY_USERNAMEandSAFEGUARD_REGISTRY_PASSWORD. -
Use one step per environment. Each step gets its own
--environment, and each environment's build is recorded as its own version, for exampleprod-1.4.2orstaging-1.4.2. You can fail on critical findings in production and set no--fail-onin development. With--wait,--fail-onacceptscritical,high,mediumorlow. -
Compare before and after. The image is recorded under its repository, one version per environment and tag, so the version built from your pull request sits next to the version currently in production. The difference is your evidence that the base change worked.
-
Gate promotion in the platform. Policies and gates (GA) are evaluated in Safeguard. The published post on plain English security policies to release gates walks through creating one. A gate that blocks KEV listed criticals in production images is a sensible first rule.
-
Merge, build, push, deploy. Deploy by digest, not by a mutable tag, so the image you scanned is the image that runs. NIST SP 800-190 section 4.2.2 recommends deploying immutable, specific versions rather than trusting a "latest" label.
The published post on tracking container images per environment goes deeper on environment names, registry credentials and fail thresholds.
What a good result looks like
You are looking for three things in the comparison:
- Inherited findings dropped. The findings you attributed to the base in Step 1 are gone or reduced.
- Nothing new and severe arrived. A newer base can bring newer packages with their own CVEs. Check the new findings, not just the totals.
- Your own findings are unchanged. Findings from your
RUNlines and your application dependencies should be the same as before. If they changed, something else changed in the build.
If the count did not move, suspect a cached base layer, an edited builder stage while the final stage keeps the old base, or a tag the publisher has not rebuilt yet.
Step 5: fix what is left in your own layers
Once the base is current, the remaining findings are yours. They come in three kinds, and each has its own fix.
OS packages your Dockerfile installs
If a package appears in your image but not in your base, your Dockerfile installed it. In order of preference:
- Remove it if the service does not need it at runtime. Build tools, download tools and version control clients often survive from a build step. Safeguard's container FAQ lists "Don't include build tools in final image (multi-stage builds)" and "Remove package manager caches" under image hygiene.
- Move it to a build stage so it never reaches the final image.
- Upgrade it in the same
RUNline that installs it, then rebuild. Putting the upgrade in a separate, earlier layer that the cache reuses defeats the point.
The published post on running apt upgrade inside a container versus rebuilding the image covers the trade offs in more detail.
Application dependencies
Application packages inside the image are the same packages your repository scan sees. Fix them in the repository, then rebuild. Safeguard's autonomous remediation (GA) can open a fix pull request that moves the dependency to a safe version, on one repository or in bulk with one pull request per repository, with breaking change detection. It ships switched off, with every category set to Manual, so your team decides what runs on its own. The published post on autonomous remediation in Safeguard explains the categories and strategies.
Compiled binaries
If a Go or Rust binary in your image carries a vulnerable library, the fix is in that binary's build. Update its dependencies, rebuild the binary, then rebuild the image. If the binary comes from a third party, check whether a newer release exists and pin to it.
Step 6: keep it fixed
A base image you fixed today will have new CVEs within weeks. The goal is not a clean scan once; it is a short gap every time.
Continuous scanning of the images you run
Connect your registry under Integrations in the app (part of ESSCM, GA). Safeguard's container FAQ recommends scanning images in CI before pushing, scanning production images daily, using webhooks for automatic scanning on push, and setting up alerts for new critical vulnerabilities. The registry integration is how a new CVE in a base you already shipped reaches you without a fresh build.
A rebuild cadence
Use a calendar trigger in your CI to rebuild every service image on a fresh pull of its base, scan it with the CI step, and open a pull request when the base digest changed. Weekly is common. The CI step's per environment versions make it easy to see when a rebuild cleared findings.
Docker's best practices page has a section titled "Pin base image versions" alongside "Rebuild your images often". Those two pieces of advice sound like they conflict. They do not: pin so that every build is repeatable, and rebuild on a schedule so that the pin moves forward deliberately. The published post on pinning base images by digest for repeatable rebuilds shows the mechanics.
Roll out across many services
When a base image fix lands, many services usually need it. Treat the base as a product:
- Publish an internal base image that your services inherit from, owned by the platform team.
- Rebuild the internal base first, scan it, then trigger downstream rebuilds.
- Track which services are still on the old digest. Keep the base digest in your build metadata, and use each service's per environment versions in Safeguard to confirm the inherited findings cleared.
The published post on rolling out a patched base image across many services covers this pattern in depth.
Retire stale images
NIST SP 800-190 section 4.2.2 recommends pruning registries of unsafe, vulnerable images that should no longer be used. Forgotten jobs and rollbacks pull old images, so once a fixed version is stable, remove or quarantine the old tags.
Step 7: when there is no fix yet
OS package CVEs often have no fixed revision in your distribution release, or the distribution has decided the issue does not warrant a fix in stable. What to do:
- Check that the finding is real for your build. Distributions often backport fixes without changing the upstream version number. Debian's security FAQ answers the question "the version number indicates that I am still running a vulnerable version" by explaining the backport policy and pointing you at the package changelog and the security tracker. Compare the exact package revision, not just the upstream version.
- Check whether another base fixes it. Look up the CVE on Gold Open Source to see affected and fixed versions, and scan an alternative base.
- Record an exception with an expiry. Accept the risk for a fixed period with a business justification, so the decision comes back for review when the distribution's position may have changed. The published post on writing an exception record for a base image vulnerability with no fix has a template.
- Say so in a machine readable way. If customers will ask, a VEX statement says whether the CVE affects your product. CSAF and VEX upload is GA in Safeguard. The published post on ingesting and sharing VEX and CSAF in Safeguard covers that flow.
- Remove the package if you can. A finding in a package you do not need is a finding you can delete. This is often the fastest fix of all.
For open source components where upstream has no fix, the published post on Safeguard fork and patch explains that flow.
Self-healing containers
Safeguard's docs describe self-healing containers as automation for the rebuild chain in this post. It is generally available. Here is what the docs describe:
- A four step loop. Detect a new CVE in one of your images, plan a patch, rebuild the image with your existing tests, and promote it if tests and guardrails pass.
- Three modes. Advisory, where Safeguard files a pull request against your Dockerfile repository or Kubernetes manifest repository and humans review and merge; autonomous with promotion gated, where it rebuilds and promotes to a staging tag and a human approves production; and autonomous continuous, where it promotes to production with policies still applied.
- Base image healing. For a
FROM node:20-alpinestyle line, the docs describe rebuilding against the latest digest of the same tag. - Rollback. The docs say the previous image digest is preserved so a heal can be reversed.
How to roll it out: run the manual process in this post first, start in advisory mode, where a pull request against your Dockerfile is easy to review or reject, and confirm with Safeguard which registries, CI systems and orchestrators it supports for your account.
Requirement, what Safeguard does, and what you still own
| Requirement | What Safeguard does | What you still own |
|---|---|---|
| Visibility into vulnerabilities at all image layers (NIST SP 800-190, 4.1.1) | Scans OS packages, application dependencies and compiled binaries in images (SCA, GA) | Scanning the base and the built image so you can split ownership |
| Quality gates at each stage (NIST SP 800-190, 4.1.1) | --wait --fail-on in the CI step (GA); policies and gates in the platform (GA) | Setting thresholds per environment and running the exception process |
| Frequent base layer updates from trusted, minimal sources (NIST SP 800-190, 4.1.2) | Scans candidate bases on demand with the CLI (GA); Gold Open Source Container Images directory and CVE lookups (GA, free) | Choosing the base, migrating to it and testing |
| Updates made in the image and redeployed (NIST SP 800-190, 3.1.1) | Records each rebuilt version per environment so you can compare; self-healing containers can automate the rebuild | Rebuilding, deploying and retiring old containers |
| Immutable, versioned deployments and pruned registries (NIST SP 800-190, 4.2.2) | Supports digest references for scanning; records image versions per environment and tag | Deploying by digest and pruning old tags |
| Prioritise exploited vulnerabilities (CISA KEV, FIRST EPSS) | KEV and EPSS on every finding (vulnerability management, GA) | Response timelines, including BOD 26-04 if you are a federal agency |
| Explain unfixed findings to customers | CSAF and VEX upload (GA); SBOM export in SPDX and CycloneDX (GA) | Writing accurate VEX justifications |
What Safeguard does not do
- It does not patch running containers. Every fix in this post is a rebuild and redeploy. Safeguard scans, records and gates; your pipeline builds and your orchestrator deploys.
- It does not change your base image by default. Autonomous remediation opens pull requests for application dependencies and ships switched off. Self-healing containers can rebuild images; nothing in this post depends on it.
- It does not pick your base image for you. Gold Open Source and the CLI give you data to compare candidates. The decision about glibc or musl, shell or no shell, and which distribution release to support is yours.
- It does not publish distribution fixes. If a distribution has no fixed revision for a package, no scanner can conjure one. You can switch base, remove the package, or record an exception.
- It does not split findings by layer in a single view that we could confirm. The method in Step 1 uses two scans and a comparison. Do not plan triage around a per layer column unless you see one in your account.
- It does not make reachability decisions for OS packages. The reachability docs list programming languages, not OS package managers.
- It does not test your service on the new base. The CI step scans the image. Your own test suite has to prove the service still works.
Common mistakes
Running a package upgrade in the running container. It changes one container until it restarts and leaves the image, and every other replica, unchanged. NIST SP 800-190 is explicit that updates are made in the image and redeployed.
Rebuilding with a cached base layer. The build finishes in seconds and nothing changes. Pull the base fresh and skip the cache on scheduled rebuilds.
Changing the wrong FROM line. In a multi-stage Dockerfile, only the final stage ships. Updating the builder stage's base clears nothing in the runtime image.
Treating latest as fresh. NIST SP 800-190 warns that a "latest" tag is only a label, not a guarantee of freshness. Pin by digest and move the pin on purpose.
Chasing upstream version numbers on a backporting distribution. The upstream version may look old while the package revision includes the fix. Compare exact revisions against the distribution's advisory.
Switching to a minimal base without testing at runtime. Missing certificate bundles, time zone data or shared libraries fail at startup or on the first outbound call, not at build time.
Fixing app dependencies in the image. An upgrade step in the Dockerfile for a library your lockfile controls creates drift. Fix the lockfile and rebuild.
Leaving old images in the registry. Rollbacks and forgotten jobs pull them. Prune or quarantine once the fixed version is stable.
Accepting risk without an expiry. An exception with no review date becomes permanent. Set a date every time.
FAQ
How do I fix vulnerabilities in a Docker base image?
Rebuild your image on a fresher or better base. Start by pulling the current digest of the same tag and rebuilding without cache. If the fix is only in a newer runtime or distribution release, move the tag. If most findings are in packages you never use, move to a smaller base with a multi-stage build. Scan the result with Safeguard in CI before you promote it.
How do I know which vulnerabilities come from the base image?
Scan the exact base reference from your FROM line on its own with safeguard scan --image, scan your built image, and compare. Findings in both are inherited from the base. Findings only in your image come from your Dockerfile instructions or your application dependencies.
Should I run apt-get upgrade in my Dockerfile?
Prefer a fresh base. If you must upgrade packages, do it in the same RUN line that installs them and rebuild regularly, so the cache does not freeze an old upgrade. Never run upgrades in a running container as a fix, because the image stays vulnerable.
Why does my image still show a CVE after I rebuilt it?
The usual causes are a cached base layer, a publisher that has not rebuilt the tag yet, the wrong FROM line in a multi-stage build, or a distribution that has not shipped a fix. Rebuild with a fresh pull and no cache, check the final stage's base, and compare the base digest's scan before and after.
Are distroless or Alpine images free of vulnerabilities?
No. Safeguard's container FAQ recommends minimal bases such as Alpine and distroless and says distroless images can still have vulnerabilities in the components they include. Fewer packages means fewer findings and fewer future findings, not zero.
How often should I rebuild container images?
Often enough that published fixes reach production quickly. Weekly scheduled rebuilds on a fresh pull of the base are a common baseline, with immediate rebuilds for KEV listed findings. Safeguard's FAQ recommends scanning production images daily so you know when a rebuild is due.
Can Safeguard rebuild my images automatically?
Self-healing containers can detect, plan, rebuild and promote images. Autonomous remediation, which opens fix pull requests for application dependencies, is GA but ships switched off with every category set to Manual. Neither replaces a pinned base and a rebuild process you understand.
How do I choose a secure base image?
Write down your runtime, C library and support window. Shortlist candidates from the Gold Open Source Container Images directory and the runtime's official images. Scan each candidate by digest with Safeguard, build your service on the best one in a branch, run your tests, and record why you chose it.
What should I do when a base image CVE has no fix?
Confirm the finding against the distribution's advisory, since backported fixes can hide behind old version numbers. Check whether another base fixes it. If not, record an exception with an expiry date, and publish a VEX statement if customers need to know whether it affects them.
Try it on your own images
Install the Safeguard CLI from safeguard.sh/download, scan your current image and the base in its FROM line, and see how much of the list one line owns. The Safeguard docs cover the CLI, the CI container step and registry integrations.
The rest of this post is the standard way Safeguard closes the gap between a published fix and a deployed one, and what happens when there is no fix yet. For container base images, the same split applies: rebuild when a fixed base exists, and use the options below for the open source components you build and ship when it does not.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.
3. Gold Registry: start from components that are already fixed
Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | Safeguard policies and gates in CI |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real Safeguard CLI session. It installs the CLI, opens the interactive terminal, and asks the assistant to fix a lodash CVE in a repository: it reads the finding and advisory, asks before any command that changes something, edits package.json to the fixed version, runs the install and tests, prints a summary and pushes nothing. That is the flow for the application dependency findings left in your image after the base is current: fix the lockfile in the repository, then rebuild the image.
Click through it at your own pace, or open it full screen.
The second demo sets up the local runner on your own machine, approves it with its device code, and then scans from the terminal. If you want to compare candidate base images on hardware you control before you change a FROM line, this is the setup you would start from.
Click through it at your own pace, or open it full screen.
Quick check
Your image has 120 findings. A scan of the exact base digest in your FROM line shows 95 of them. What is the fastest first move?
Rebuild on a fresh pull of the same tag without the layer cache, update the pinned digest, and scan the new base on its own first. If the publisher has rebuilt the tag, many of the 95 inherited findings clear with a one line change. Then deal with the 25 that belong to your own layers.
You updated the base image, rebuilt, and the CI scan shows the same CVEs. What do you check?
Check that you changed the final stage's FROM line in a multi-stage build, that the build pulled the base fresh and did not reuse a cached layer, and that the new base digest's own scan actually lacks those CVEs. If the distribution has not shipped a fix, record a dated exception and look for another base.
Sources
- NIST SP 800-190, Application Container Security Guide (CSRC page)
- NIST SP 800-190 full text (PDF)
- NIST SP 800-218, Secure Software Development Framework
- CISA Known Exploited Vulnerabilities Catalog
- CISA BOD 26-04: Prioritizing Security Updates Based on Risk
- FIRST Exploit Prediction Scoring System (EPSS)
- OCI Image Manifest Specification
- Docker docs: Multi-stage builds
- Docker docs: Building best practices
- Docker docs: Dockerfile reference
- Debian security FAQ
- Distroless container images project
- Safeguard docs: CI/CD container images
- Safeguard docs: Container image integration FAQ
- Safeguard docs: Self-healing containers
- Gold Open Source: Container Images directory
- Gold Open Source
Last reviewed: 24 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.