Software composition analysis (SCA) is a security testing technique that inventories the third-party and open-source components an application depends on, direct and transitive, and checks each specific version against vulnerability and malware intelligence. Fluid Attacks' documentation defines it as a technique that "automatically identifies the third-party dependencies or libraries that an application uses." The unit it works on is the version, not the package name.
On November 4, 2026 alone, the Fluid Attacks Database published 67 malware advisories: 62 for npm, three for PyPI and two for RubyGems. Not one of them had a CVE. An SCA that only matches components against CVE feeds would have reported every project using them as clean.
This page covers what SCA inventories, what it detects and what it does not, how direct and indirect dependencies are resolved, how reachability and exploitation data change which findings matter, and where our own SCA stops. It treats the software supply chain as an operational problem, not a compliance checkbox.
What is SCA?
SCA is the practice of building an accurate dependency inventory of the code your application uses but your team did not write, and then assessing the risk each entry carries. It reads the files where open-source dependencies are declared, resolves what those dependencies in turn pull in, and matches the resulting list of component-and-version pairs against security intelligence.
The output is two things: the inventory itself, usually exportable as a Software Bill of Materials, and a set of findings tied to specific versions in specific files.
What SCA is not
SCA does not read your own code for insecure patterns. That is Static Application Security Testing. It does not test a running application. That is Dynamic Application Security Testing. And SCA is not a synonym for generating a bill of materials: that document is an output, while the analysis is the work of deciding which of its entries are dangerous and why.
The distinction matters because teams that treat SCA as document generation end up with an accurate list of components and no idea which of its hundreds of entries to act on first.
What SCA detects, and what it does not
SCA as a category covers more ground than any single product implements. OWASP's Component Analysis guidance lists fifteen risk factors for a third-party component, including component age, repository trust, provenance, pedigree, license, inherited risk and project health. A known vulnerability is one of the fifteen, not the whole picture. OWASP also notes that components that are "end-of-life (EOL) or end-of-support (EOS) also impact risk," which no CVE feed will tell you.
Products split that ground differently, so the honest answer to "what does this detect" depends on whose tool you mean. Ours is deliberately narrow:
Capability | SCA as a category | Fluid Attacks' SCA |
|---|---|---|
Inventory of direct and transitive components | Yes | Yes |
Disclosed vulnerabilities per version (CVE and advisories) | Yes | Yes |
Malicious and compromised packages | Depends on the product | Yes, with our own advisory IDs |
Reachability of the vulnerable function | Only where implemented | Yes, deterministic, in 14 languages |
SBOM export | Yes | Yes, CycloneDX and SPDX |
Outdated and unmaintained components | Yes | Reported as part of the security assessment |
License compliance | Frequently included | No. Out of scope |
Code quality of components | Sometimes included | No. Out of scope |
Our documentation states the limit plainly: "Fluid Attacks SCA is for application security only and detects only security issues," and it "does not detect other types of issues, for example software quality or legal issues." If open-source license compliance is a requirement for your organization, a tool built for security will not cover it, and ours says so rather than implying otherwise.
SCA at Fluid Attacks
Our SCA runs as part of a continuous assessment of the repositories you connect, not as a scan you launch. Here is what it inventories, where it goes beyond matching a package list against the NVD, and where it stops.
What we inventory, and from what
We perform SCA on the files where you declare your dependencies: the manifests and lock files of the package managers we support across the JavaScript, Python, Java, Go, Ruby, PHP, C# and Swift ecosystems. Code copied from a third party and pasted into your repository is reported separately, as a non-upgradable dependency, because there is no version to bump.
Every entry in the package inventory carries the repository and the files it appears in, the advisories affecting that version, and the stage where it is used: build, when the file depends on the component "only in the software development stage," or run, when it depends on it "in the live production environment." That last field is what separates a vulnerable test harness from a vulnerable component shipping to production.
Malware advisories, not just CVE matches
A package can be malicious without ever receiving a CVE. Our database treats that as its own weakness class, 448, "Use of software with malware": "One or more dependencies used in the project contains code or components suspected of being compromised by malware or malicious behavior." It maps to three of our security requirements, including "Verify third-party components."
That class is fed by intelligence a CVE feed does not carry. Of the 18 data sources behind our catalog, one is OpenSSF Malicious Packages, a feed of confirmed malicious publications rather than disclosed flaws. The result is public and continuous: those November 4 advisories, for packages such as nminer on npm and extera-runtime on PyPI, carry our own identifiers rather than CVEs, because no CVE exists.

Malware advisories published on November 4, 2026. None of them carries a CVE.
Deterministic reachability, not probabilistic
Knowing a vulnerable version is present is not the same as knowing your application can trigger it. Our reachability analysis resolves whether the vulnerable element is actually invoked, and it does so deterministically, by following the call path, rather than estimating likelihood.
Our comparison documentation records how that sits against two other vendors, as of the tables' October 2026 update:
Attribute | Fluid Attacks | Snyk | Black Duck |
|---|---|---|---|
Reachability | 14 languages | 5 languages | Not offered |
Reachability type | Deterministic | Probabilistic | — |
Malware detection | Yes | Yes | No |
Vulnerability sources | 18 | 9 | 5 |
Container distributions | 4 | 15 | Not specified |
Source: Fluid Attacks' comparison with Snyk and with Black Duck.
The limits
The last row of that table is not in our favor, and it is the first thing to check before you adopt any SCA. We cover four container distributions. A team whose risk sits mostly inside base images, rather than in application manifests, will find broader coverage elsewhere.
Two more limits worth stating. We do not apply fixes to your dependencies automatically across the board: the scanner recommends the safe version, and in JavaScript and Python projects our IDE extension can apply that change to the manifest for you, flagging the lock file if that update fails. And, as noted above, license and quality findings are out of scope. An SCA that claims all fifteen OWASP risk factors is usually claiming a roadmap.
Review the diff, not just the repository
Dependencies enter in a pull request. Our Peer Reviewer Assistant "reviews the code changes of a pull request or a merge request (PR/MR)" and runs three scanners on them, including SCA, which reports "vulnerabilities in the dependencies that the change affects." It works on cloud-hosted repositories in GitHub, GitLab and Azure DevOps.
That is where the measurable difference shows up. In Fluid Attacks' State of Attacks 2026, covering 1,119,396 vulnerabilities reported between January 1 and December 31, 2025, organizations using our CI Gate remediated 72.2% of their reported vulnerabilities, against 58% among those that did not.
It runs alongside SAST, DAST and Pentesting as a Service (PTaaS), so a dependency finding is triaged next to what pentesting found in the same app.
Go deeper: reachability analysis explains how the call path is resolved and what a non-reachable verdict does and does not prove.
How SCA resolves direct and transitive dependencies
A direct dependency is one your project declares. A transitive dependency is one your direct dependencies bring in, often several layers down, and resolving it correctly is the hardest thing an SCA does, because most of the inventory lives there.
Our SCA labels each import in each file with one of three states:
Label | Meaning | What you do with it |
|---|---|---|
D — Direct | "The file in your project explicitly imports and uses the third-party dependency" | Upgrade the declared version |
T — Transitive | "The third-party dependency is required by your direct dependencies," without the file importing it | Follow the path to the direct parent, or pin an override |
U — Undeterminable | "It is impossible to determine whether the dependency is direct or transitive" for that file | Treat as present until resolved manually |
For transitive entries, the platform traces the path. In the documented example, the direct dependency grunt-if leads to the vulnerable transitive dependency y18n, and the path shows every hop between them. Without that path, an SCA finding reaches a developer as an alert about a package that appears nowhere in their manifest.

The platform traces the path from the direct dependency grunt-if to the vulnerable transitive dependency y18n.
Log4Shell is the case that made this unavoidable: thousands of organizations ran a vulnerable logging library they had never declared, inherited through frameworks and plugins, and answering the question at all meant having the resolved tree an SCA produces. Regulators drew the same conclusion. The 2026 Minimum Elements for a Software Bill of Materials, published on July 29, 2026 by CISA with NSA, FBI and fifteen international partner agencies, says an SBOM should cover all components "including transitive dependencies. There is no minimum depth." The 2021 baseline it replaces asked for top-level dependencies only.
Why SCA matters: four risks a scanner has to separate
Bundling every software supply chain problem into one alert queue is what makes SCA output unusable. These four risks behave differently and need different responses.
Known vulnerabilities in a specific version
The same package can be safe and vulnerable at once, depending on the version pinned. Our component catalog, which held more than 233,000 open-source components when consulted on November 5, 2026, records status per version: lodash, for instance, has 116 versions tracked on npm, some marked safe and others carrying several advisories each.

Version, not package name, is what decides whether a dependency is vulnerable.
Compromised and malicious packages
In September 2025, a phishing email from a lookalike domain took over a prominent npm maintainer's account and pushed malicious versions of 18 widely used packages with roughly 2.6 billion combined weekly downloads; our analysis of that campaign traced malware that rewrote cryptocurrency wallet addresses in the browser. Six days later, Shai-Hulud used stolen npm tokens to publish malicious versions of other packages owned by each maintainer it reached, spreading on its own. And in March 2025, a compromised GitHub Action used by more than 23,000 repositories printed CI/CD secrets into workflow logs.
The UK's NCSC reached the same conclusion in June 2026, warning that "malicious code introduced into a single package can spread rapidly across many organisations and services before detection" and naming maintainer account compromise, abandoned package takeover, typosquatting and self-propagation as the recurring techniques.
Unmaintained components and project health
A component with no known flaws can still be a liability if nobody maintains it. Our posts on undersupported digital infrastructure and the Nebraska joke of xkcd #2347 make the case that critical projects are often kept alive by a handful of unpaid people. The 2016 removal of left-pad from npm broke builds across the ecosystem, and it was no attack: dependency risk includes availability, not only compromise.
Writing about SCA in 2018, Fluid Attacks security analyst Rafael Ballestas put the responsibility for choosing components well where it belongs:
"it is not FOSS's fault if applications use it with known vulnerabilities but rather that of the apps' owners."
Dependencies that keep changing after the build
A vulnerability can be disclosed the week after you ship, and nothing in your code changed when it was. A point-in-time audit of a repository is a snapshot, which is why the dependency inventory has to be monitored for "updates, security advisories and reachable vulnerabilities" rather than exported once and filed.
This is also what makes SCA different in practice from the other scanners in a CI/CD pipeline: a SAST finding appears because someone wrote a line of code, while an SCA finding can appear on a branch nobody has touched in months.
How to prioritize SCA findings
Severity alone is a poor queue, and it is the main reason SCA output gets ignored. A single vulnerability record in our database carries the signals that actually decide order, and they frequently disagree with each other:
Signal | What it answers |
|---|---|
CVSS, original and adjusted | How bad is it in the abstract, and in this context |
EPSS with percentile | How likely is exploitation in the next 30 days |
CISA KEV | Is it being exploited right now |
Exploit and PoC evidence | Does working attack code exist |
Reachability capability | Can your code actually reach the flaw |
Transitivity | Is it yours to fix, or your dependency's |
Stage of use | Build-only, or running in production |
Any SCA emits the first row. The rest separates a queue you can work through from a list you archive.
The disagreement is the point. One record we publish carries an original CVSS v3.1 score of 8.1 High and an adjusted CVSS v4.0 score of 5.2 Medium, with an EPSS of 2.81% and no KEV evidence. Treating it as a High because the first number says so moves work away from something that is genuinely being exploited.

One record carries exploitation data, KEV status, reachability capability and an adjusted severity score.
SCA, SAST and SBOM are not alternatives
These three get used interchangeably and answer different questions.
SCA | Static analysis | Bill of materials | |
|---|---|---|---|
What it examines | Declared dependencies and their versions | Your own source code | Nothing. It is a document |
What it produces | Findings tied to a component version | Findings tied to a line of code | An inventory of components |
Question it answers | Am I using something dangerous? | Did I write something dangerous? | What am I using at all? |
The first two are complementary rather than competing, and combining them is what makes reachability possible: you need the component list to know what is present and the code analysis to know whether it is called. The bill of materials is the artifact SCA emits, and it is covered on its own page.
How to implement SCA
Start where dependencies enter. Running SCA only on the default branch means every vulnerable package is already merged by the time anyone sees it, so scan pull requests and break the build on what violates policy.
Define the policy before the first scan, in terms your team can act on: which severities block a merge, how exploitation data and reachability modify that, and who owns a transitive finding that needs an upstream fix. Vulnerability management decides what happens after the alert; the scanner only decides what the alert says.
Judge any SCA against your own stack, not a feature list. The questions that separate these products are narrow: which package managers it resolves, whether it detects malicious publications or only disclosed flaws, whether it traces transitive paths or lists names, whether reachability is deterministic or estimated, and what it covers inside containers.
Conclusions
SCA earns its place when it answers a harder question than "is this package on a list." The attacks that compromised npm in 2025 and 2026 did not produce CVEs on the day they mattered, and an SCA limited to disclosed flaws reports those projects as clean. Judge an SCA on its malware intelligence, on whether it traces transitive paths, on whether it can tell you the vulnerable function is reachable, and on whether it is honest about where it stops.
Frequently asked questions
Can SCA detect malicious packages that have no CVE?
Only if it ingests malware intelligence, not just vulnerability feeds. A malicious package is often a legitimate project whose maintainer account was compromised, and no CVE is ever assigned. Fluid Attacks publishes these as their own advisory class: 67 malware advisories appeared in our database on November 4, 2026 alone — 62 for npm, three for PyPI and two for RubyGems — and none of them carried a CVE.
Does SCA scan transitive dependencies?
A good one does, and this is where most of the inventory lives. Our platform labels every import as direct, transitive or undeterminable, and for transitive findings it traces the path back to the direct dependency that introduced them. Since July 2026, CISA's minimum elements require that coverage with no minimum depth, so a tool that stops at the top level no longer meets the baseline.
What is the difference between SCA and an SBOM?
An SBOM is a document listing the components in a piece of software. The analysis is what produces that document and then assesses what is in it. You can hold a complete, standards-compliant SBOM and still not know which of its entries is exploitable.
How does reachability analysis change SCA results?
It separates presence from exposure. A vulnerable version in your dependency tree is only exploitable if your code reaches the vulnerable element. Fluid Attacks resolves this deterministically in 14 languages. A non-reachable verdict lowers priority; it does not prove the component is safe, since a later code change can make it reachable.
Does Fluid Attacks' SCA detect license or software quality issues?
No. Our documentation states that our SCA "is for application security only and detects only security issues" and "does not detect other types of issues, for example software quality or legal issues." It inventories your open-source dependencies, exports SBOMs in CycloneDX and SPDX, and reports security findings. License compliance needs a separate tool.
Know what you are shipping
Our Software Composition Analysis inventories every dependency your application pulls in and tells you which versions are dangerous, which are reachable and which are carrying malware. Start free trial · Contact us.
Get started with Fluid Attacks' SSCS solution right now















