Most SCA tools were designed for application codebases, not container images. They parse package manifests—package.json, requirements.txt, pom.xml—and analyze the declared application dependencies against CVE databases. This approach works well for the problem it was designed to solve: identifying vulnerable application libraries in source code.
Container images are a different artifact. They combine OS-level packages installed by the base image, system libraries that application packages depend on, language runtime packages, and application-level dependencies—all in a single filesystem that isn’t a codebase and doesn’t have a single package manifest.
SCA tools that treat container images like application codebases—scanning only the language-level package manifests they find inside the image—miss the majority of the container’s component inventory and CVE surface.
The Layer Structure of Container Package Inventory
A production container image typically contains packages from multiple layers:
OS package layer: The base image installs OS packages through the distribution package manager (dpkg, rpm, apk). An Ubuntu base image includes hundreds of packages covering system utilities, cryptography libraries, network tools, and language runtimes. These packages are installed, tracked by the package manager database, and vulnerable to CVEs against their versions—but they don’t appear in any application package manifest.
System library layer: Language runtimes depend on system libraries (glibc, OpenSSL, libcurl) that are installed as OS packages or compiled into the runtime. CVEs in these libraries affect every application that uses them, but they’re invisible to SCA tools that only read application language manifests.
Language runtime packages: Python’s standard library, Node.js’s built-in modules, and the Java standard library all include packages with CVE histories. These arrive with the runtime installation, not through the application’s dependency manager.
Application-level packages: The packages the development team explicitly declared in their manifests. This is the layer that manifest-based SCA tools cover.
For a container with 400 installed packages, the application manifest might declare 40. SCA that covers only the manifest covers 10% of the package inventory.
What Container-Level SCA Requires?
Container-level SCA operates on the installed package inventory—what’s actually in the container filesystem—rather than on manifests that describe what was intended to be installed.
OS package detection
Container vulnerability scanner tools that query the OS package manager database directly retrieve the authoritative list of installed OS packages, their versions, and their source. Tools that try to infer OS package presence from filesystem artifacts are less reliable—package manager databases provide complete, accurate inventories.
OS package scanning coverage is verifiable: scan the image, extract the package list, compare against what the base image’s official manifest documents. Gaps indicate incomplete OS-layer scanning.
Binary artifact and embedded library detection
Some container images include binary artifacts—pre-compiled executables, Java JAR files, embedded libraries—that don’t appear in any package manager database. These binaries contain their own CVE-vulnerable components. SCA tools that only query package manager databases miss binary-embedded vulnerabilities.
Container image security assessment that includes binary analysis—scanning executables for embedded library signatures, descending into JAR files to extract their dependencies—provides coverage for components that arrived outside the package manager.
Transitive dependency resolution at the container level
Container-level scanning captures transitive dependencies that arrived in the container regardless of dependency depth. A package installed at the OS layer has its own dependencies installed alongside it; those dependencies appear in the package manager database and are captured by container-level scanning even if they weren’t in any application manifest.
This is the Log4Shell lesson applied to OS packages: transitive dependencies that arrived without explicit declaration are still part of the CVE surface.
Runtime Profiling: The Coverage Layer Beyond Static Inventory
Static container-level SCA produces a complete inventory of what’s installed. It doesn’t indicate which installed packages actually execute when the container runs.
For prioritization purposes, the distinction matters: a CVE in a package that the application never loads has no execution path. Runtime profiling of containers under production-representative load identifies which OS packages, language packages, and application packages are loaded during execution—separating the active inventory (worth prioritizing for remediation) from the dormant inventory (worth removing entirely).
The combination of complete static inventory (container-level SCA) and execution-confirmed inventory (runtime profiling) provides:
- Compliance completeness: The static SBOM documents everything installed, satisfying inventory requirements
- Operational prioritization: The runtime profile identifies what needs remediation versus what can be removed
- Attack surface reduction: Confirmed-dormant packages are removed, eliminating their CVEs permanently
Practical Steps for Container-Specific SCA
Evaluate SCA tools against a test container with known contents. Build a test image with a specific set of OS packages and application packages, then scan with candidate tools. Compare the scan output against the known contents—gaps in OS-level coverage are immediately visible.
Verify base image package coverage specifically. Base images contribute the majority of OS-layer packages. Scan the base image alone and compare the tool’s output against the base image’s official package manifest. Coverage gaps at the base image level indicate the tool’s OS scanning limitations.
Test embedded binary analysis with JAR-in-JAR scenarios. Java Spring Boot fat JARs embed dependencies in a nested structure that many scanners miss. Scan a Spring Boot application and verify that the embedded dependencies appear in the output.
Use container-level SCA output as the SBOM for compliance purposes. Compliance requirements for SBOM generation (EO 14028, FedRAMP, customer contracts) require documentation of what’s in the delivered software. Container-level SCA that captures the full installed package inventory produces a more complete compliance SBOM than manifest-based SCA that covers only declared application dependencies.
Frequently Asked Questions
What is software composition analysis for containers and how does it differ from standard SCA?
Software composition analysis for containers operates on the full installed package inventory of a container image—querying the OS package manager database, scanning binary artifacts, and resolving transitive dependencies—rather than just parsing application manifests like requirements.txt or package.json. Standard SCA tools designed for application codebases cover only the application-level packages a development team explicitly declared, which typically represents around 10% of the total package inventory in a production container.
Why does container SCA need to go beyond language packages?
Container images contain packages from multiple layers that language-level SCA tools miss entirely: OS packages installed by the base image’s distribution package manager, system libraries like OpenSSL and glibc that runtimes depend on, and binary artifacts such as pre-compiled executables or embedded JAR files. The Log4Shell incident illustrated this precisely—transitive dependencies that arrived without explicit declaration in any manifest were still part of the CVE surface and required remediation across every container that included them.
How does runtime profiling complement software composition analysis for containers?
Static container SCA produces a complete inventory of what is installed but cannot indicate which packages actually execute when the container runs. Runtime profiling of containers under production-representative load identifies which packages are loaded during execution, separating the active inventory that warrants remediation priority from the dormant inventory that can be removed entirely. Removing confirmed-dormant packages through hardening eliminates their CVEs permanently rather than just tracking them.
How should container SCA output be used for compliance purposes?
Container-level SCA that captures the full installed package inventory produces a more complete SBOM than manifest-based SCA covering only declared application dependencies. This complete inventory satisfies compliance requirements under EO 14028, FedRAMP, and customer contracts that require documentation of what is in delivered software—regulators and customers expect the delivered artifact’s actual component inventory, not just the application-level subset that a manifest-scanning approach documents.
Container Security Requires Container-Native Analysis
SCA tools designed for application codebases adapted to container images—scanning for language manifests inside the container filesystem—provide partial coverage of a much larger attack surface. Container-native analysis that treats the installed package database as the authoritative inventory, scans binary artifacts for embedded components, and combines static analysis with runtime profiling provides complete coverage.
The investment in container-native SCA isn’t incremental over application SCA—it’s a different analysis scope that addresses the full attack surface that containers represent.