Posted in

The Hidden Open-Source Risks Lurking in Your Container Images

Your containers are built on open source. The base image is open source. The language runtime is open source. The frameworks, libraries, and utilities your application depends on are open source. This is true for virtually every containerized application in production today.

This is not a problem with open source. Open source enables the infrastructure we rely on. But it creates a specific security challenge: the open-source packages in your container images are visible to every security researcher and every attacker simultaneously. CVEs discovered in those packages are publicly disclosed. The window between disclosure and exploitation is short.

The hidden part of this risk is not the CVEs in packages your application uses. Those are visible, trackable, and remediable. The hidden risk is the CVEs in packages your container includes but your application never calls.


How Open-Source Package Risk Accumulates in Container Images?

Container images are built by layering. A base image brings hundreds of packages. Language runtimes bring their own ecosystems. Application dependencies bring transitive dependency trees that expand far beyond what the developer specified.

At each layer, packages are added. Each package has a CVE history. The CVE history grows over time as researchers discover and disclose vulnerabilities in code that has been in production for years.

The accumulation pattern:

Ubuntu 22.04 base: ~350 packages, ~250 CVEs in a fresh pull (the Ubuntu CVE count changes daily as new vulnerabilities are disclosed against packages in the base image)

Python 3.11 runtime layers: +40 packages, their CVE history

Direct application dependencies: +25 packages specified in requirements.txt

Transitive dependencies: +40-60 packages pulled automatically to satisfy direct dependency requirements

Total: 450-475 packages, 350-500 CVEs

Of these CVEs, how many are in packages the application actually calls? Typically 30-50. The remaining 300-450 CVEs are in packages that the container image contains but the application never executes.

“The open-source risk in your container images is not primarily in the packages you chose. It is in the packages that came along for the ride.”


The Transitive Dependency Blindspot

Developers specify direct dependencies. Developers rarely track transitive dependencies in detail. Package managers — pip, npm, apt, maven — resolve the full dependency graph automatically and install everything.

A Django application with 12 direct dependencies might install 50 packages total. The developer reviewed the 12 they chose. The other 38 were added by the package manager to satisfy those 12 choices.

Each of those 38 packages is an open-source project with its own CVE history. The developer did not make a security decision about them. They were installed automatically. They are in the container image. They carry CVEs.

Software composition analysis (SCA) tools can identify these transitive dependencies and their CVEs. The challenge: knowing which CVEs are in transitive dependencies does not tell you which transitive dependencies your application actually uses.

A transitive dependency that was installed automatically but is never imported by your application code or its direct dependencies is attack surface with zero application value. Removing it is pure security improvement.


The Execution Path Approach to Open-Source Risk

The distinction that changes your risk model: installed packages versus executed packages.

A secure software supply chain approach to open-source risk requires knowing which open-source packages in your container image are actually executed at runtime. Not which are installed — any scanner can tell you that. Which are actually called by your application’s code paths during real operation.

This is determined by runtime profiling:

  1. Run the application with profiling instrumentation enabled
  2. Capture which packages, modules, and libraries are loaded or called during execution
  3. The executed packages are your genuine open-source dependency set
  4. Everything installed but not executed is removable attack surface

The security posture improvement from this approach is dramatic: most container images have 60-80% of their open-source package footprint in packages that are never executed. Removing these packages eliminates 60-80% of CVEs with zero impact on application functionality.


What Remains After Component Removal?

After runtime-profile-based package removal, the remaining open-source risk is cleaner to manage:

The packages are all used: Every CVE finding from a scanner is in a package that your application depends on. No more triage to determine which findings are in unused packages.

Upgrade paths are clearer: When a CVE is disclosed in a used package, the fix is to upgrade that package. The dependency is real; the upgrade path is bounded.

Risk acceptance is defensible: When a CVE exists in a used package that cannot immediately be upgraded (no fix available, breaking changes in the upgrade, vendor-imposed version constraints), the risk acceptance decision is based on an actual dependency that provides application value.

Compliance evidence is tighter: An SBOM that shows 50 packages with their CVEs is more auditor-friendly than an SBOM showing 450 packages. The minimal-footprint SBOM is the genuine risk inventory.



Frequently Asked Questions

What are the three major types of risks when using open source in container images?

The three major risk categories are vulnerability risk (publicly disclosed CVEs in open-source packages that attackers can exploit), supply chain risk (compromised maintainer accounts, typosquatting, or dependency confusion that introduces malicious code), and footprint risk (transitive dependencies that are installed automatically but never used by the application, expanding the attack surface beyond what developers intentionally included). Container image security must address all three, but the footprint risk is the most commonly overlooked.

What are the hidden open-source risks in container images?

The hidden risk is not the CVEs in packages your application actively uses — those are visible and trackable. The hidden risk is the CVEs in transitive dependencies that were installed automatically by the package manager to satisfy your direct dependencies but are never called by your application code. A typical Python web application installs 40–60 packages to satisfy 12 direct dependencies; the application may execute only 25–30 of them. The remaining packages carry CVEs while contributing nothing to application function.

What is container image security and why does it matter for open-source software?

Container image security is the set of practices used to identify, reduce, and monitor vulnerabilities in the packages and dependencies bundled inside a container image. It matters for open-source software because the open-source packages in your images are publicly visible to both security researchers and attackers simultaneously — CVEs are disclosed publicly and exploitation windows are short. Without understanding which open-source packages in your container are actually executed versus merely installed, you cannot accurately assess or reduce your real exposure.

How can you reduce open-source CVE risk in container images without breaking the application?

The most effective method is runtime profiling: run the application with profiling instrumentation, capture which packages and modules are actually imported and executed, and remove packages with zero execution evidence. This approach typically eliminates 60–80% of CVEs in a container image because most installed packages are never called during actual operation. The remaining CVEs are all in packages the application genuinely depends on, making every finding actionable.


The Catalog Approach to Open-Source Image Management

Container image software that maintains a curated catalog of hardened images for popular open-source software changes the economics of open-source risk management.

Rather than each team individually profiling, hardening, and maintaining security for their instance of Nginx, Postgres, Redis, or Node.js, a pre-hardened catalog provides images that have been profiled and hardened against common usage patterns. Teams pull the hardened image from the catalog rather than the official Docker Hub image.

The catalog model:

  • Profiling is done once for each common image/usage pattern
  • Hardening is applied centrally
  • CVE monitoring applies across the catalog
  • When upstream images update, catalog images are re-hardened automatically

For organizations with large numbers of teams using common open-source base images, the catalog approach eliminates redundant hardening work while maintaining consistent security properties across all consumers.

Open-source risk in container images is systematic, not random. It concentrates in predictable package categories — system utilities, networking tools, package managers — that are present by default but unused in production. Addressing it systematically through execution-path analysis produces the largest security return of any container security investment.