version v7.2.
For up-to-date documentation, see the
latest version.
Software Composition Analysis
11 minute read
Modern applications rarely consist of only custom code. They rely on dozens or even hundreds of open-source and third-party components. Software Composition Analysis (SCA) is the practice that focuses on securing what you did not write yourself. It is a key part of a Secured Software Development Lifecycle.
Objectives
SCA pursues two objectives:
Inventory components — identify everything the application depends on (declared or not) and produce a Software Bill of Materials (SBOM). Depending on the analysis approach, the resulting SBOM is a Source SBOM (built from manifests and source code), a Build SBOM (captured at build time), or an Analyzed SBOM (built from a compiled artifact or container image).
Analyze at build time — on every build, verify the absence of:
- known vulnerabilities ,
- operational risks (outdated, abandoned or end-of-life components),
- legal issues (incompatible licenses, export control constraints).
The SBOM produced by SCA is also the foundation that enables, beyond SCA itself, continuous monitoring: alerting when an already-delivered component becomes vulnerable following the publication of a new CVE.
What Is a Dependency?
A dependency is any piece of code your application relies on that you did not write yourself, whether open-source (OSS) or commercial (COTS).
How dependencies are integrated
Which dependencies matter depends on what you deliver:
Application dependencies — present in every project:
- Declared (direct) — explicitly listed in a manifest or lockfile (pom.xml, package.json, go.mod, package-lock.json, yarn.lock…).
- Transitive — pulled indirectly by your direct dependencies, often several layers deep.
- Copied / vendored — source code copy-pasted or embedded in the repository, without any manifest or lockfile entry.
System dependencies — relevant when the deliverable includes an operating system (container image, VM image, appliance):
- OS packages — libraries and tools installed via the system package manager (dpkg, rpm, apk).
- Dynamically linked libraries — shared libraries (.so, .dll) resolved at runtime, provided by an OS package.
If you only deliver application code (a JAR, an npm package, a Go binary…), application dependencies are your focus. As soon as you ship a container image or a VM, the OS packages inside it become part of your supply chain and must be analyzed too.
A single direct dependency can pull in dozens of transitive ones. Since transitive dependencies represent the vast majority of an application’s dependency tree, they are also where most vulnerabilities are found.
Your Application
├── express@4.18.0 (direct)
│ ├── body-parser@1.20.0 (transitive)
│ │ └── qs@6.10.3 (transitive)
│ └── cookie@0.5.0 (transitive)
└── lodash@4.17.21 (direct)
Analysis Approaches
Dependencies can be identified at different stages of the development lifecycle and through different mechanisms — each suited to a specific type of dependency, with its own trade-offs. The sections below describe the main analysis approaches, what each can and cannot detect, and when in the lifecycle it applies. They follow the CISA SBOM taxonomy , which classifies SBOMs by when they are produced: Source, Build, and Analyzed.
Source Analysis
Source analysis operates directly on the repository, without compiling the application. It produces a Source SBOM.
Manifest and lockfile analysis is the most common and reliable approach. The tool reads language-specific dependency files — pom.xml, package-lock.json, go.sum, yarn.lock… — and resolves the full dependency tree against structured registries (npm, Maven Central, PyPI…). Because registries provide authoritative metadata, results are fast and accurate with low false positive rates. This approach covers declared direct dependencies and all their transitives, but cannot detect copied or vendored code absent from any manifest.
Snippet matching scans the actual source code and matches fragments against a large knowledge base of known open-source components. This is the only approach that can detect copied or vendored source code — dependencies embedded directly in the repository without any manifest entry.
This approach is particularly relevant for C and C++ projects. The absence of a standardized package manager (Conan and vcpkg remain minority options) has made vendoring the norm: SQLite amalgamation, stb single-file headers, embedded OpenSSL or zlib are typical examples. Without snippet matching, these dependencies are entirely invisible to manifest-based tools.
Snippet matching is also increasingly used to detect AI-generated code that may inadvertently reproduce licensed open-source fragments.
The trade-off is complexity: the tool must maintain a large, curated fingerprint database, and results may include false positives requiring manual review.
A Source SBOM reflects what is declared in the sources — not necessarily what is actually resolved at build time. Version conflict resolutions and build-time overrides may differ from what manifests declare.
Build Analysis
Build analysis instruments the build process itself. It produces a Build SBOM.
The build tool (mvn, gradle, npm, etc.) is instrumented to record the exact dependency
graph as it is resolved at build time — including version conflict resolutions that may differ
from what manifests declare.
This is the most accurate reflection of what actually goes into the artifact.
Analyzed Analysis
Analyzed analysis inspects a compiled or packaged artifact, without requiring access to source code or build manifests. It produces an Analyzed SBOM.
Two techniques exist, with very different mechanisms:
Package metadata inspection extracts package information from structured metadata embedded in the artifact: JAR manifests, container image layer databases, OS package managers (dpkg, rpm, apk). Like manifest analysis, this is reliable because it relies on structured, authoritative metadata. It covers all packages embedded in the artifact — including OS-level packages in container images.
Binary fingerprinting identifies embedded components by matching binary patterns and hashes against a knowledge base, even when no structured metadata is present. This is the only approach that can audit third-party binaries (COTS, vendor-supplied libraries) where neither source code nor package metadata is available. The trade-off is accuracy: without structured metadata, identification relies on heuristics and may produce false positives or miss heavily obfuscated components.
When to Apply SCA
SCA is most effective when applied at multiple stages of the development lifecycle.
Before committing (IDE / CLI) — scanning dependencies locally provides the earliest possible feedback, before they enter the codebase.
This is the most impactful shift-left practice for SCA: it prevents vulnerable dependencies
from reaching the CI pipeline, reducing rework and review cycles.
Native package manager tools (cargo audit, npm audit, govulncheck, pip-audit…) provide
fast, accurate local feedback for their specific ecosystem and require no extra setup.
Xray users can complement these with jf audit or the JFrog IDE extension for
cross-ecosystem coverage.
In the CI pipeline — the minimum requirement. Every merge request and build is automatically checked without manual action. This is where policy enforcement (quality gates) blocks non-compliant components from being merged or deployed.
In the artifact registry — server-side scanning at indexation time catches issues that source-level scanning may miss, and enables policy enforcement at the distribution level (blocking download or promotion of non-compliant artifacts).
Continuous monitoring goes beyond SCA itself: once an SBOM is produced, a dedicated server (Xray, Black Duck, Dependency-Track…) can re-evaluate already-inventoried components against newly published CVEs — without requiring a new build or pipeline run.
Policy Management
Scanning alone only lists problems. Policy management turns scan results into automated decisions by defining rules that determine whether a component is acceptable or not.
A policy combines criteria (what triggers the rule) with actions (what happens when it triggers):
| Criteria | Action |
|---|---|
| CVE with Critical severity | Block build / merge request |
| Incompatible license (e.g., GPL in a proprietary project) | Block and notify legal team |
| End-of-life component | Block or warn |
| Component unpatched for more than 2 years | Warn and create ticket |
This is what transforms an informational scan into a quality gate: instead of merely reporting issues, the tool makes a pass/fail decision based on rules defined by the team or the organization.
Policies can be enforced at every stage described above — in the IDE (warning), in CI (blocking the pipeline), or on the server (blocking download or deployment).
SCA Tools in Software Factory
The Software Factory suite includes three SCA analysis tools:
The native security scanning feature built into GitLab CI/CD, requiring no additional tooling.
The security analysis layer of the JFrog Platform, tightly integrated with Artifactory.
An enterprise SCA platform providing comprehensive open-source risk and license management.
Choosing Your SCA Toolchain
There is no one-size-fits-all SCA toolchain. The right choice depends on several factors:
- Analysis depth — manifest scanning covers most projects; snippet matching or binary analysis require specialized tooling and dedicated effort to triage results.
- Project technologies — not all tools support every language or package manager equally.
- Budget — some tools are included with existing licenses; others require separate procurement.
- Team capacity — advanced tools produce richer results but demand time to manage findings.
- Platform constraints — not every tool is deployable in every environment; air-gapped or offline platforms may restrict the available options.
- Governance or contractual requirements — the toolchain may be prescribed at GBU, Business Line, or customer contract level, leaving little room for local choice.
The tiers below offer a reading grid — not prescriptions. Your context may call for a different combination, and organizational or contractual requirements may override any local choice.
Avoid using different tools for the same type of analysis on the same scope. Mixing tools produces inconsistent results and makes vulnerability management harder.
Before choosing a tier, note that each tool has a distinct center of gravity — and speaks to a different persona:
- GitLab SCA around the GitLab experience (developers) — results surface natively in merge requests and dashboards without any extra setup.
- JFrog Xray around the artifact registry (ops and delivery teams) — its value comes from the Artifactory coupling, continuous monitoring of deployed artifacts, and registry-level policy enforcement.
- Black Duck around analysis depth (security and compliance teams) — snippet matching, legal-grade compliance, and richer vulnerability intelligence that the other tools cannot match.
The tiers below are ordered from the simplest to adopt to the most comprehensive. Start from your current situation and move up as your needs grow.
Tier 1 — GitLab SCA
The simplest entry point — limited to what GitLab natively detects. Dependency Scanning and Container Scanning integrate directly into the CI pipeline with no additional tooling — results surface in merge request widgets, the vulnerability report, and the dependency list out of the box.
This covers manifest/lockfile analysis and container OS package scanning, producing a Source SBOM and an Analyzed SBOM on every build.
Limitations: no IDE scanning, no continuous monitoring, no registry-level policy enforcement.
Both tools are included in the DevSecOps offer.
If your language is not supported by GitLab Dependency Scanning, native package manager tools
(cargo audit, npm audit, govulncheck, pip-audit…) provide a basic fallback for that
specific ecosystem — no platform required, but no SBOM generated either.
Tier 2 — GitLab SCA + JFrog Xray

GitLab SCA handles CI feedback as in Tier 1. JFrog Xray , coupled with Artifactory, adds registry-level capabilities that GitLab cannot provide:
- Analyzed SBOM — Artifactory indexing scans artifacts at push time, covering container layers, nested archives, and embedded dependencies.
- Continuous monitoring — already-indexed artifacts are re-evaluated against newly published CVEs without requiring a new build.
- Registry-level policy enforcement — artifacts can be blocked at download or promotion time.
The two tools cover different scopes and do not conflict: GitLab operates at CI/merge request level, Xray at the registry level. Additional setup is required (Xray indexing, watches and policies).
Both tools are included in the Software Factory package at no additional cost.
For teams wanting Xray as the sole scanning tool: replace GitLab Dependency Scanning with BuildInfo in CI — it captures the exact dependency graph as resolved at build time, producing a more accurate Build SBOM. Results live in the Xray UI rather than GitLab’s dashboard, and the setup is more involved (BuildInfo integration, Xray watches and policies).
Tier 3 — Black Duck
The deepest analysis available — for projects where detection accuracy and compliance are critical. Black Duck runs in the CI pipeline like the other tools, but its value lies in analysis power rather than registry integration:
- Snippet matching — detects vendored or copy-pasted open-source fragments and AI-generated code that manifest-based tools cannot see.
- Legal-grade license compliance — copyright extraction and obligation tracking, beyond basic license detection.
- Deeper vulnerability intelligence — BDSA advisories offer richer context and faster publication than public databases.
The trade-off: no registry integration with Artifactory. An additional license cost applies on top of the Software Factory package.
Tool Capability Matrix
The three tiers above cover most situations, but your context may call for a different combination — specific platform constraints, budget limits, or a preference for community-supported tooling. The table below provides a full capability breakdown of every SCA tool available in the Software Factory ecosystem, including open-source community alternatives, so you can make an informed decision when the recommended tiers do not apply.
Support levels are indicative and reflect general trends at the time of writing. They evolve quickly with tool updates and depend heavily on the specific technologies and use cases being analyzed. Always refer to the tool’s official documentation for up-to-date details.
| Capability | GitLab SCA | JFrog Xray | Black Duck | Community |
|---|---|---|---|---|
| Inventory | ||||
| Source — manifest / lockfile | ✅ Dependency Scanning | ✅ jf audit | ✅ Detect | ✅ Trivy / Grype / pkg audit |
| Source — snippet matching | ❌ | ❌ | ✅ Detect | ❌ |
| Build | ❌ | ✅ BuildInfo | ❌ | ❌ |
| Analyzed — package metadata | ✅ Container Scanning | ✅ jf scan / Indexing | ✅ Detect | ✅ Trivy / Grype |
| Analyzed — binary fingerprinting | ❌ | ❌ | ✅ Detect | ❌ |
| SBOM generation | ✅ CycloneDX | ✅ CycloneDX, SPDX | ✅ CycloneDX, SPDX | ✅ Trivy / Syft |
| Analysis | ||||
| Vulnerability detection | ✅ Advisory DB | ✅ JFrog DB | ✅ BDSA | ✅ Trivy / Grype / pkg audit |
| Operational risk | ❌ | ⚠️ Operational Risk | ✅ EOL, maintenance | ❌ |
| License compliance | ⚠️ Basic | ✅ | ✅ Legal-grade | ⚠️ Detection only |
| Integration | ||||
| IDE / local | ❌ | ✅ JFrog extension | ✅ Code Sight | ✅ Trivy CLI |
| CI pipeline | ✅ Native | ✅ JFrog CLI | ✅ Detect | ✅ Trivy / Grype / pkg audit |
| Registry | ❌ | ✅ Artifactory | ❌ | ❌ |
| Continuous monitoring | ❌ | ✅ | ✅ | ⚠️ Dependency-Track |
Legend: ✅ fully supported · ⚠️ partial support · ❌ not supported