Application Security

SCA (Software Composition Analysis)

Inventories the open-source and third-party dependencies inside an application and matches them against known vulnerabilities and license obligations.

What is software composition analysis?

Software composition analysis (SCA) inventories the open-source and third-party dependencies inside an application and matches them against known vulnerabilities and licence obligations. It answers a narrow, valuable question: what external code is being shipped, and is any of it known to be flawed?

Key takeaways

  • SCA is essential and it produces enormous volume. A modern application resolves hundreds of transitive dependencies, and one flawed package flags across every service that includes it.
  • It is a presence check. The analysis establishes that a vulnerable version is in the dependency tree. It does not establish that anything calls the vulnerable function.
  • Transitive dependencies dominate the output. Most flagged packages were never selected by a developer; they arrived as a dependency of a dependency, several levels down.
  • Fixes break things. Upgrading one package frequently breaks another, and the break is usually not in the package that was upgraded.
  • Reachability is what makes the output actionable. Adding a callability check removes the large majority of findings from the set that warrants immediate work.

Why it matters

Developers learn quickly that most of an application security queue is not exploitable, and the rational response to a low-precision signal is to deprioritize all of it, including the findings that matter. More scanners or more urgency makes that worse, because it raises volume without raising precision.

The second problem is the shape of the request. A raw finding hands a developer an investigation rather than a task: which version resolves the advisory, does that version break anything downstream, what else depends on this package, and when is there a testing window. That investigation is the real cost, and it lands on an engineering budget rather than a security one, which is why counts of findings closed correlate so poorly with reduction in risk.

How SCA works

  • Dependency resolution. Manifests and lock files are parsed to build the full tree, direct and transitive, ideally at the resolved-version level rather than the declared range.
  • Identifier matching. Resolved package coordinates are compared against vulnerability databases using package URLs or equivalent identifiers.
  • Binary and artifact scanning. Some implementations also inspect built artifacts, container images and vendored code, which catches dependencies that never appear in a manifest.
  • Licence analysis. Most tools flag licence obligations and incompatibilities, a separate concern that happens to need the same inventory.
  • Inventory export. The resolved tree can be emitted as a software bill of materials in a standard format for downstream or contractual use.

What SCA does not establish

Four questions sit outside the scope of a composition scan, and all four determine whether a finding deserves attention. Whether the vulnerable function is called from application code. Whether attacker-controlled data can reach the vulnerable parameter. Whether the upgrade required to resolve the advisory will break the build or the runtime. And which team owns the repository, which decides whether anything happens at all. These are the boundary of the technique rather than defects in it: composition analysis reads dependency metadata, while the remaining questions need call graph analysis, data flow analysis, build verification and ownership attribution.

The upgrade problem, concretely

Bumping NumPy to 2.0 is an application binary interface break that kills pandas, SciPy and scikit-learn builds compiled against the 1.x series. A bot proposes the single version bump, every check in the pipeline goes green because nothing in the test matrix exercises the compiled path at import time, and the application dies on start-up in the next environment. The same shape recurs constantly, from urllib3 2.0 against a pinned botocore to hundreds of quieter equivalents in every ecosystem.

The correct fix is almost never the single package named in the advisory. It is the coordinated set of versions that satisfies both the advisory and the compatibility constraints of everything depending on it. A finding naming one package and one target version understates the work by an order of magnitude.

How to evaluate an SCA capability

  • Resolution fidelity. Does the tool report the version actually resolved by the build, including transitive pins and lock file overrides, rather than the range declared in a manifest.
  • Reachability depth. Presence, load, function reachability and data reachability are distinct layers. A tool stopping at presence produces a much larger and less precise queue.
  • Advisory provenance. Which databases are consulted, how quickly advisories are ingested, and whether version ranges are curated or copied verbatim.
  • Fix modelling. Whether the output proposes a coordinated upgrade set with compatibility reasoning, or a single bump a developer must validate manually.
  • Ownership resolution. Whether a finding routes to a named team derived from repository history and code ownership metadata, or lands in a shared queue.

Common misconceptions

  • That SCA and SAST overlap. Static application security testing analyses first-party code. Composition analysis inventories third-party code. Most organizations need both, and the finding populations barely intersect.
  • That an unreachable finding is a false positive. The library really is present and really is vulnerable. It is a true finding that is not currently exploitable, which should be recorded rather than deleted.
  • That the number of findings measures risk. It measures dependency breadth. A monolith with one vulnerable shared library can generate more findings than a fleet of services with genuine exposure.
  • That automated version bumps solve it. They solve the trivial cases and create work in the rest, because an incompatible upgrade often fails after the pipeline has passed.

Standards and sources

Inventory output is normally expressed in SPDX, standardized as ISO/IEC 5962, or CycloneDX, an OWASP specification designed with security use cases foremost. Advisory data flows from the CVE Program, national vulnerability databases and ecosystem-specific sources, increasingly exchanged through the OpenVEX and CSAF formats, which exist to communicate that a present component is not affected. NIST Special Publication 800-218 is the usual reference for where composition analysis sits in a development lifecycle.

FAQ

Is SCA the same as SAST? No. Static application security testing analyses code written in-house. Software composition analysis inventories the third-party code pulled in as dependencies. Most organizations need both.

Why are there so many SCA findings? Transitive dependencies. A handful of chosen packages each bring their own, and a flaw deep in the tree flags in every application that resolves it.

Does reachability mean unreachable findings can be ignored? It means they are not urgent. They should stay in the record, because a change in how the code is called can make a previously unreachable finding reachable.

Can SCA find vulnerabilities in code that was not declared as a dependency? Only if it inspects built artifacts. Vendored source, shaded jars and copied files do not appear in a manifest, so manifest-only analysis will miss them.

Sources

  • OWASP, CycloneDX Bill of Materials Specification version 1.6, 2024.
  • Linux Foundation, SPDX Specification version 3.0 (ISO/IEC 5962), 2024.
  • NIST, Special Publication 800-218: Secure Software Development Framework version 1.1, 2022.
  • Apache Software Foundation, Log4j Security Advisory for CVE-2021-44228, 2021.
  • Verizon, 2026 Data Breach Investigations Report.