top of page

Software Supply Chain Security in Practice: From Threats to SCA and SBOMs

Sep 22
25 min read

Updated: 3 days ago


1 Introduction


Historically, software security focused on in-house code, with teams reviewing developer output, running static analysis, and auditing completed applications. This approach assumed organizations authored most of their software. Today, that is no longer the case, and security concerns now extend across the entire delivery chain.


The demand for faster delivery and greater returns has reshaped software engineering. Today, applications are built from open-source libraries, infrastructure frameworks, third-party SDKs, managed cloud services, and outsourced CI/CD pipelines, with proprietary code comprising only a small portion. LLM-assisted and agent-driven development further accelerates this shift, as agents generate code, select dependencies, and configure pipelines faster than manual review can keep up.


Each external component brings its own supply chain and vulnerabilities, expanding the attack surface. Focusing solely on first-party code ignores significant risks within the broader system.


Figure 1 - Typical application dependencies graph overview

Figure 1 - Typical application dependencies graph overview


Attackers quickly adapted. In the SolarWinds incident, they compromised the vendor's build system and inserted backdoors into signed updates, reaching thousands of organizations through a trusted channel. A year later, Log4Shell (CVE-2021-44228) revealed another dimension: a single remote code execution flaw in Log4j, one of the most used libraries in the Java world, deeply embedded in dependency trees, exposed much of the world's software, often in systems whose owners were unaware they used it.


Attackers increasingly target trusted components rather than direct breaches. Typosquatting, where malicious packages use names similar to popular ones, has evolved into a highly automated and significant threat to software supply chains and enterprise pipelines. All ecosystems are affected, including established platforms like NuGet (.NET), Maven Central (Java), PyPI (Python), and npm (Node.js). According to Sonatype, repository abuse, including typosquatting and package confusion, accounts for 55.9% of all logged malicious packages. Dependency confusion is similar: a public package named after a company's internal one can mislead build tools into downloading it.


These attacks extend beyond human error. Research indicates that about 20% of packages recommended in AI-generated code samples do not exist. Because models often repeat invented names, attackers can preemptively register them, a technique called "slopsquatting." If an AI agent adds dependencies without verification, a single fabricated name can introduce a vulnerability.


The issue is substantial in scale. A typical Node.js project may have hundreds of transitive dependencies, while a large Spring Boot application can exceed a thousand. Managing only direct dependencies is inadequate, as threats often arise transitively. Security professionals need comprehensive methods to evaluate, monitor, and remediate risks across the entire dependency graph.


Figure 2 - Example of dependency graph of a Spring Boot-based application

Figure 2 - Example of dependency graph of a Spring Boot-based application


Addressing risks of this scale and variety takes more than adding another scanner to the pipeline. It requires treating everything that goes into software, and everything that happens to it on the way to production. Before looking at how to do that, it helps to define the terms precisely.


The software supply chain is anything and everything that touches an application or plays a role, in any way, in its development throughout the entire software development life cycle (SDLC).

Software supply chain security (SSCS) is the practice of securing the components, activities, and practices involved in creating and deploying software. That includes every component, tool, dependency, and process involved in building, testing, and deploying an application, including protection against tampering and malicious insertion. The supply chain covers everything that touches code across the SDLC, from proprietary code and open source libraries to CI/CD pipelines, build tools, registries, and deployment infrastructure.


Governments and industry have since formalized the terminology and requirements. In 2021, U.S. Executive Order 14028 dedicated a section to software supply chain security, calling for Software Bills of Materials (SBOMs) and automated vulnerability checks of third-party components, the core of Software Composition Analysis (SCA).

To help organizations navigate this evolving landscape, Plexteq has developed software supply chain best practices to address emerging threats.


2 Exploring the Problem


In the absence of a standard definition of a software supply-chain attack, we propose the following three-part definition:

  1. A software supply-chain attack is the insertion of malicious source code into trusted software before delivery.

  2. A software supply-chain vulnerability is an exploitable weakness in trusted software caused by a third-party component.

  3. Software supply-chain security is the engineering of defenses against software supply-chain attacks and vulnerabilities.


Software supply-chain attacks are not limited to open source. In 2012, attackers broke into Juniper Networks and altered the source code of its VPN products, swapping constants in a random number generator. The change created a backdoor that let attackers decrypt Juniper customers' VPN traffic. Because the software was modified before delivery, this was a supply chain attack, even though the code was proprietary.


Second, attackers don't have to touch the original software at all; tampering with how it is distributed is enough. In 2015, researchers found that attackers had published a modified copy of Apple's Xcode on Chinese file-sharing sites, which local developers often preferred for faster downloads, and promoted it to the top of Chinese-language search results. The tampered build, later named XcodeGhost, silently injected malware into every iOS app compiled with it, and infected apps reached the App Store, including widely used ones.


Third, the affected application doesn't need to be open source to suffer from an open source weakness. Log4Shell, discussed above, is the clearest example: in Minecraft, a closed-source game, a single crafted chat message was enough to execute code on the server through the embedded Log4j library.


Deliberate attacks follow the same path. In 2018, the popular npm package event-stream was found to carry obfuscated code designed to steal bitcoin wallets, but only when bundled into the Copay wallet app, a commercial product that was the intended target all along. Since nearly all proprietary software is built on open source components, its security depends directly on the health of the open source supply chain.


Figure 3 - Cumulative malware packages by ecosystem for 2025

Figure 3 - Cumulative malware packages by ecosystem for 2025


Finally, attacks can run entirely within open source. In 2024, the XZ Utils backdoor targeted OpenSSH not through its own code but through liblzma, a compression library in its dependency chain, after a multi-year campaign in which the attacker gained maintainer trust. It was discovered largely by chance. Had it gone unnoticed a few months longer, a back-doored SSH daemon would have shipped in major Linux distributions and ended up on servers worldwide.


These incidents illustrate software supply-chain security breaches. The remainder of this article outlines key principles for stronger defenses and practical steps organizations are implementing today.


3 Understanding the Software Supply Chain


Securing the software supply chain starts with understanding it. The supply chain encompasses every point where an attack could occur or a vulnerability could be introduced. The greater challenge is achieving a complete view of the supply chain, which most organizations lack.


Technically, the supply chain includes your code and configuration, proprietary and open-source binaries, libraries, plugins, and container images. It also encompasses the tools that convert code into running software: build orchestrators, compilers, assemblers, code analyzers, artifact repositories, and the security, monitoring, and logging tools used in operations. More broadly, it extends to the people, organizations, and processes behind these elements.


Figure 4 - An example of hidden transitive dependency

Figure 4 - An example of hidden transitive dependency


Each element can be a target for tampering or a source of vulnerabilities. Achieving full visibility requires identifying who maintains each dependency, who has access now or in the future, and what infrastructure supports them. Few organizations can answer these questions, leaving risks unaddressed. These risks persist regardless of oversight.


Mapping the supply chain helps prioritize which links need reinforcement. While the industry continues to evolve, many effective defenses are already established. The following sections discuss these measures.


4 Anatomy of a Software Supply Chain Attack


A typical software supply chain attack occurs in multiple stages, targeting weak points in the development and delivery lifecycle. The following outlines the progression of such attacks:


Figure 5 - Stages of software supply chain attack

Figure 5 - Stages of software supply chain attack


1. Reconnaissance and target selection

The attacker begins by identifying important targets, often focusing on widely used open-source projects, CI/CD systems, or package registries. Public repositories and dependency metadata may contain information on potential entry points.


2. Initial compromise

Attackers exploit supply-chain vulnerabilities. This might entail compromising a developer’s account, injecting code into a third-party package, or gaining unauthorized access to the CI/CD pipeline. Phishing, credential stuffing, or exploiting known CVEs are common methods at this stage.


3. Payload insertion

Once access is secured, the attacker inserts a malicious payload, often obfuscated or disguised to bypass detection, into the targeted component. In open-source attacks, this could mean committing code to a repository or publishing a tampered version of a legitimate package.


4. Propagation

The compromised component is distributed through legitimate channels such as package managers or CI/CD pipelines. Developers or systems integrating the affected software unknowingly propagate the attack further, embedding malicious code across downstream applications.


5. Execution and impact

The payload activates once deployed in target environments, enabling data exfiltration, privilege escalation, or remote access. Because the malicious code is embedded deep in the supply chain, detection is delayed, increasing the attacker’s dwell time and impact.


6. Persistence and evasion

To maintain access and avoid detection, attackers may use techniques such as backdoors, code obfuscation, or conditional payload triggering. Some campaigns aim to remain through software updates or avoid triggering static analysis tools.


5 Tools and Technologies for Supply Chain Protection


No single tool covers the whole supply chain. In practice, organizations combine several categories, each addressing a different stage of the software lifecycle.


Software Composition Analysis (SCA)

SCA tools scan applications to identify open source and third-party components, including transitive dependencies, and match them against known vulnerabilities and license requirements. This provides teams with a clear understanding of their software's composition, forming the basis for other controls. Modern SCA tools integrate with CI/CD pipelines to flag or block vulnerable packages before production and often suggest fixes or automatically open upgrade pull requests. Continuous monitoring is essential, as a dependency that was safe yesterday may have a critical CVE published today.


Software Bill of Materials (SBOM)

An SBOM is a machine-readable inventory of all components in a software product, including versions, suppliers, and other metadata. Its value is most evident during incidents. For example, when Log4Shell was disclosed, organizations with current SBOMs identified affected systems within hours, while others spent weeks searching. SBOMs are typically generated during the build process using tools like Syft or CycloneDX plugins and are published in CycloneDX or SPDX formats. Regulations such as EO 14028 increasingly require software suppliers to provide SBOMs.


Dependency and Package Management Security

Package managers like npm, PyPI, Maven, and NuGet simplify reuse, making them attractive targets for attackers. Registry protections such as mandatory two-factor authentication, package signing, and build provenance help prevent account hijacking and tampered releases. On the consumer side, best practices include pinning dependencies with lockfiles for reproducible builds, using private or vetted proxy repositories, and blocking unreviewed new packages. Reserving internal package names and configuring build tools to resolve them only from internal registries counters dependency confusion, while checks for similar names help detect typosquatting and slopsquatting.


Build and CI/CD Pipeline Integrity

As the SolarWinds case showed, attackers who control the build process can distribute malicious code under a vendor's signature. Build provenance, generated by platforms like GitHub artifact attestations, records what was built, from which source, and by which pipeline, enabling consumers to verify artifacts before deployment. Sigstore streamlines signing: a CI job authenticates via OIDC, signs with cosign using a short-lived certificate, and logs the signature in the public Rekor transparency log.

Runners and secrets need equal care. Ephemeral, isolated runners, least-privilege job permissions, and third-party actions pinned to commit hashes limit incidents like the 2025 tj-actions/changed-files compromise, which leaked secrets from thousands of repositories. Short-lived OIDC credentials should replace long-lived keys, with any remaining secrets kept in a secrets manager such as HashiCorp Vault and backed by secret scanning.


Threat Intelligence and Vulnerability Databases

Security tools are only as effective as their underlying data. Sources like the National Vulnerability Database (NVD), Open Source Vulnerabilities (OSV), GitHub Security Advisories, Sonatype OSS Index, and vendor feeds provide information on known vulnerabilities and malicious packages. Integrating this data into SCA tools and pipelines enables automated alerts and prioritization.

CVSS severity alone is insufficient, as many high-scoring CVEs are never exploited. Mature teams also consider exploitation signals such as CISA's Known Exploited Vulnerabilities catalog, EPSS scores, and whether the vulnerable code is actually reachable in their application.


Runtime Protection and Monitoring

Preventive controls cannot detect every threat, especially attacks designed to evade scanning, such as the XZ backdoor. Runtime tools provide a final layer of defense by monitoring software behavior during execution. Runtime application self-protection (RASP), container and workload security tools, and extended detection and response (XDR) platforms flag or block unexpected network connections, unusual system calls, and unauthorized code or memory changes. Forwarding these alerts to a SIEM integrates them with the organization's incident response.


Application Detection and Response (ADR)

ADR is a newer category focused on application-level behavior. It uses telemetry from running applications, such as file access, system calls, and network activity, to establish a baseline of normal behavior and detect deviations that static analysis and pre-deployment testing miss. For example, a dependency that unexpectedly reads credentials or a build tool that initiates outbound connections may indicate supply chain tampering, which ADR is designed to detect.


6 Key Standards and Frameworks for Supply Chain Security


Tools demonstrate how to protect the supply chain, but do not define what constitutes sufficient protection. Without a shared reference point, organizations may accumulate scanners without knowing if they address the right risks, how mature their processes are, or how to demonstrate compliance to customers and regulators. Standards and frameworks address this gap by defining target states, integrating tools into a coherent program, and providing a common language for developers, security teams, and suppliers.


SLSA (Supply Chain Levels for Software Artifacts)

SLSA, short for Supply Chain Levels for Software Artifacts, is a security framework Google developed to improve the integrity of software artifacts throughout the development lifecycle. It provides a maturity model with four progressive levels (SLSA 1-4), each defining stricter security controls for source integrity, build provenance, and dependency management.

SLSA is based on verifiable build provenance, an artifact that proves how, when, and by whom a software artifact was built. Higher SLSA levels require tamper-resistant build environments and cryptographically signed attestations. By following SLSA, organizations can prevent unauthorized modifications and detect tampering before deploying software.


NIST Guidelines

The National Institute of Standards and Technology (NIST) has published multiple documents to guide organizations in securing their software supply chains. Notably, NIST SP 800-161 Rev. 1 focuses on supply chain risk management (SCRM) practices for federal systems, and the NIST Secure Software Development Framework (SSDF) provides detailed practices for integrating security into the software development process.

NIST guidelines emphasize identifying critical suppliers, securing development environments, assessing third-party software, and maintaining a thorough incident response plan. These documents serve as foundational resources for aligning with regulatory requirements and implementing supply chain risk management strategies.


ISO/IEC 27001 Extensions for Supply Chains

ISO/IEC 27001 is a widely recognized standard for information security management systems (ISMS). While the core standard outlines high-level controls, its supporting standard ISO/IEC 27036 addresses supply chain information security. It outlines practices for securing information exchanged between organizations and their suppliers.


ISO/IEC 27036 emphasizes supplier vetting, contractual security requirements, and ongoing monitoring of third-party relationships. By extending an organization’s ISMS to the supply chain, ISO standards help ensure consistent, enforceable security controls across vendors and partners.


Across these frameworks, a clear pattern emerges: they require the outcome, a complete component inventory, a shareable SBOM, and continuous monitoring of third-party code, while leaving the tools to each organization. NIST's SSDF ties SBOMs directly to EO 14028, ISO/IEC 27036-3 describes what a supplier's SBOM should contain, and ISO/IEC 27001 expects evidence that supply chain vulnerabilities are managed. SLSA assumes an organization already knows what goes into its builds.


Organizations meet these expectations through SCA and SBOMs. SCA is the practical method for tracking thousands of direct and transitive dependencies at modern development speeds, while the SBOM standardizes these findings for auditing, sharing, and rapid response to new vulnerabilities. Knowing exactly which components you are protecting makes all other controls more effective, making SCA and SBOMs the logical starting point and focus of this article.


7 From Principles to Practice


Each tool addresses a specific aspect of the problem. However, no organization can implement all of them simultaneously, and pursuing every category at once often results in dashboards rather than improved security. The key question is where to begin.


For most teams, the starting point is visibility. All other controls depend on understanding your software's composition: you cannot verify the provenance of an unknown artifact, prioritize vulnerabilities in unidentified components, or respond to incidents like Log4Shell without knowing where affected components reside. SCA and SBOMs provide this essential visibility.


7.1 What is an SBOM?


SBOM definition: An SBOM, or Software Bill of Materials, is a detailed inventory of the code components, libraries, and dependencies used in building an enterprise software application, including open-source and third-party components.


Figure 6 - Parts of SBOM artifact

Figure 6 - Parts of SBOM artifact


An SBOM provides transparency by listing all open-source and proprietary components, including their versions, potential vulnerabilities, and relationships. SBOMs help organizations identify risks, ensure license compliance, and respond quickly to vulnerabilities. They are increasingly important for meeting security and regulatory requirements because they improve visibility and trust in software products.


Example of an SBOM. This example represents a simple Node.js application that uses one external dependency (lodash).


{
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58ef34f3d4f",
  "version": 1,
  "metadata": {
    "timestamp": "2026-09-21T21:15:00Z",
    "tools": [
      {
        "vendor": "CycloneDX",
        "name": "Node.js BOM Generator",
        "version": "2.1.0"
      }
    ],
    "component": {
      "bom-ref": "my-app@1.0.0",
      "type": "application",
      "name": "my-app",
      "version": "1.0.0"
    }
  },
  "components": [
    {
      "bom-ref": "pkg:npm/lodash@4.17.21",
      "type": "library",
      "name": "lodash",
      "version": "4.17.21",
      "description": "Lodash modular utilities.",
      "hashes": [
        {
          "alg": "SHA-256",
          "content": "449b6d194541bf762d3a3f55d88686d1ee176b92f4daaa03b019b84b553655df"
        }
      ],
      "licenses": [
        {
          "license": {
            "id": "MIT"
          }
        }
      ],
      "purl": "pkg:npm/lodash@4.17.21"
    }
  ],
  "dependencies": [
    {
      "ref": "my-app@1.0.0",
      "dependsOn": [
        "pkg:npm/lodash@4.17.21"
      ]
    }
  ]
}

Key Elements of this SBOM:

  • Metadata: Identifies the main software asset (my-app), the creation timestamp, and the tool used to generate the SBOM.

  • Components: The actual inventory of libraries. In this cut-out, it lists lodash, its exact version, license (MIT), cryptographic hash for security verification, and Package URL (purl).

  • Dependencies: Maps the relationships, showing that my-app relies directly on lodash.


7.2 What is SCA?


Software Composition Analysis (SCA) is a security tool category that identifies open source and third-party components in your codebase, catalogs them in a software bill of materials (SBOM), and continuously monitors them for security vulnerabilities and license compliance issues.


SCA answers three questions that no other security tool can:

  1. What third-party code are you running? Most developers can name their direct dependencies. Almost none can list the full transitive dependency tree.

  2. Are any of those components vulnerable? SCA tools cross-reference your dependency versions against CVE databases updated in real time.

  3. Are your licenses compatible? A GPL-licensed transitive dependency buried six levels deep can force disclosure of your proprietary source code. SCA tools surface these conflicts before your legal team finds them in an audit.


Figure 7 - Typical SCA outputs

Figure 7 - Typical SCA outputs


7.3 Compliance & Regulatory Use


SCA – Often used as a security tool but not directly tied to compliance regulations


SBOM – Increasingly required by regulatory bodies. For example, in May 2021, the US government’s Executive Order on Improving the Nation’s Cybersecurity emphasized the importance of SBOMs.



SCA

SBOM

Functionality

Identifies vulnerabilities, malware and licensing issues in OSS and third-party components and guides remediation

Inventory list of all components in an enterprise software application

Codebase

OSS and other third-party components

The entire codebase

Frequency

Ongoing

Periodic

Vulnerability and Malware Detection

Yes

No

License Compliance Detection

Yes

Support

Monitoring

Continuous

No

Remediation

Yes

Support

Required for Compliance

No

Yes

SCA and SBOMs provide different security controls, but they complement each other and enhance an enterprise's security posture:

  • SCA tools can create an SBOM based on their scans, including components, licenses, and versions.

  • SCA tools can use SBOMs to identify vulnerabilities and malware by analyzing components against external databases and the vendor’s internal research.


In summary, an SBOM establishes what components are present, while SCA continuously monitors those components for open source security risks and compliance issues.


7.4 Where SCA Fits Among Security Testing Tools


To understand where SCA fits in your security stack, you need to know what each tool type covers.


Tool type

What it analyzes

What it finds

Blind spots

SCA

Third-party and open source dependencies, including transitive ones

Known CVEs, license violations, known malicious packages, outdated or unmaintained components

Zero-days and not-yet-reported malicious packages; code copied into the repo without a manifest entry; whether a vulnerable function is actually reachable (unless the tool does reachability analysis)

SAST

Your own source code, without running it

Injection flaws, hardcoded secrets, insecure coding patterns, unsafe API use

Runtime and configuration issues; vulnerabilities inside dependencies; tends to produce false positives

DAST

The running application, from the outside, like an attacker

Authentication and session flaws, misconfigurations, injection and XSS exposed through the interface

Code paths it doesn’t reach; exact location of the flaw in the source; dependency risk that doesn’t surface externally

IAST

The running application from the inside, via instrumentation during testing

Vulnerabilities confirmed at runtime and traced to the exact line of code, including in libraries on executed paths

Code not exercised by tests; requires an instrumented test environment; limited language and framework support

RASP

The application in production, via runtime instrumentation

Active exploitation attempts and anomalous behavior, which it can block, including from compromised dependencies

Doesn’t fix root causes; adds performance overhead; only sees attacks that actually happen

IaC and pipeline configuration scanning

Terraform, Kubernetes manifests, Dockerfiles, and CI/CD workflow definitions

Misconfigurations, over-privileged jobs, unpinned third-party actions, script injection in workflows

Runtime drift from the declared configuration; issues in external systems the pipeline calls

SCA does not replace SAST, DAST, or other tools; each addresses a different security layer.


A SQL injection in your own code is detected by SAST, while the same flaw in an imported library is identified by SCA. Both are equally exploitable, and neither tool detects the other's findings.


The strongest security posture results from layering these tools: SCA and SAST on every commit in the CI pipeline, IaC and pipeline configuration scanning for build and deployment, DAST and IAST for testing in staging, and RASP for protection in production.


Together, these tools address code written by developers, imported components, build and deployment processes, and runtime behavior.


7.5 SBOM for Compliance


To maintain continuous compliance and security, store SBOMs in a centralized, immutable repository that links each unique build artifact to its exact dependency manifest.


In regulated sectors such as healthcare (FDA), defense (DoD), automotive (ISO 21434), and finance (DORA), losing track of historical SBOMs creates significant legal and operational risks.


When a critical vulnerability like Log4j is discovered, regulators expect immediate answers. Retaining only the SBOM for your latest production build is insufficient. Regulators require precise knowledge of which legacy versions, patches, and historical deployments are vulnerable. Maintaining historical SBOMs enables instant searches across your entire registry.


8 SCA Test Drive


Understanding SCA's intended function matters, but seeing how it produces findings is equally valuable. This section demonstrates a dependency scan from start to finish: identifying components from manifests and lockfiles, resolving the full dependency tree, matching each component against vulnerability and license databases, and generating actionable findings. Knowing these steps helps interpret scan results, identify false positives and gaps, and select the right tool for your ecosystem.


Figure 8 - Comprehensive SCA approach

Figure 8 - Comprehensive SCA approach


8.1 How Dependency Scanning Works


SCA tools use a defined pipeline to identify, catalog, and assess dependencies. Understanding this process helps you evaluate tools and interpret their results.


Step 1: Manifest and Lockfile Parsing

Every package manager uses manifest files to declare dependencies and lockfiles to specify exact versions. SCA tools begin by parsing these files.


{
  "name": "my-application",
  "version": "1.0.0",
  "dependencies": {
    "express": "^4.18.2",
    "lodash": "^4.17.21",
    "jsonwebtoken": "^9.0.0"
  },
  "devDependencies": {
    "jest": "^29.7.0"
  }
}


The manifest lists your direct dependencies, but version ranges like ^4.18.2 can resolve to any compatible version. The lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml) records the exact installed versions, including all transitive dependencies.


SCA tools parse both files. The lockfile supplies precise versions for vulnerability matching, while the manifest indicates whether a dependency is direct or transitive, and whether it is for production or development.


Step 2: Transitive Dependency Resolution

This step introduces significant complexity. Your package.json may list 10 direct dependencies, but your node_modules folder could contain 800 packages.


SCA tools reconstruct the full dependency tree, capturing every package, version, and relationship. This matters because most vulnerabilities hide in transitive dependencies. You may not have chosen or even know about these packages, yet they run in your production environment with full access to your application context.

For example, installing express also brings in qs for query string parsing. An older version of qs contains a prototype pollution vulnerability (CVE-2022-24999). Even if you never imported or configured qs directly, your application is vulnerable because express includes it.


Step 3: Vulnerability Database Matching

With the full dependency tree mapped, SCA tools match each component and version against vulnerability databases:

  • NVD (National Vulnerability Database): The U.S. government's comprehensive CVE database

  • GitHub Advisory Database: Community-curated advisories with package-manager-specific metadata

  • OSV (Open Source Vulnerabilities): Google's distributed vulnerability database spanning multiple ecosystems

  • Vendor-specific databases: Snyk, Sonatype, and other commercial SCA vendors maintain proprietary vulnerability intelligence


Each vulnerability entry includes a severity score (CVSS), affected version ranges, fixed versions (if available), and exploit metadata. Advanced SCA tools also perform reachability analysis to determine whether your code actually calls the vulnerable function, not just whether the library is present.


Step 4: License Analysis

SCA tools extract license declarations from each package and flag conflicts. Common issues include:

  • Copyleft contamination: A GPL-licensed dependency in a proprietary application may require you to open-source your code

  • License incompatibility: Combining packages with mutually exclusive licenses (e.g., GPLv2 and Apache 2.0 in certain configurations)

  • Missing licenses: Packages with no declared license default to full copyright — you have no legal right to use them


Step 5: Reporting and Prioritization

Raw vulnerability counts are not useful. An application with 200 flagged CVEs needs triage. Modern SCA tools prioritize findings based on:

  • CVSS score: How severe is the vulnerability?

  • Exploitability: Is there a known exploit in the wild?

  • Reachability: Does your code actually invoke the vulnerable code path?

  • Fix availability: Is there a patched version you can upgrade to?

  • Environment: Is this a production dependency or a dev-only tool?


A critical-severity, exploitable, reachable vulnerability in a production dependency with a fix available demands immediate action. A low-severity issue in a dev-only dependency with no known exploit can wait.


8.2 What SCA Tools Catch


Dependency scanning covers more risks than most developers realize. Here is what modern SCA tools detect.


Known CVEs in Open Source Libraries

This is the core SCA use case. When a researcher discovers a vulnerability in an open source library and a CVE is assigned, SCA tools flag every project using affected versions. This includes:

  • Remote code execution vulnerabilities like Log4Shell

  • Prototype pollution in JavaScript libraries

  • Deserialization flaws in Java libraries

  • Path traversal in file-handling packages

  • Denial of service vulnerabilities in parsers and validators


License Compliance Violations

Enterprise SCA tools maintain license databases and policy engines. You define which licenses are acceptable for your organization, and the tool automatically flags violations. This prevents legal exposure from accidentally shipping copyleft code in a proprietary product.


Outdated Dependencies

Not every outdated dependency has a CVE. But outdated dependencies are a leading indicator of future vulnerabilities. A package that hasn't been updated in three years is more likely to contain undiscovered flaws, and when a CVE does drop, the upgrade path is longer and riskier.


Malicious Packages

The newest and fastest-growing SCA detection category. Malicious packages are planted in public registries through:

  • Typosquatting: Publishing lodassh or expresss and hoping developers mistype

  • Dependency confusion: Publishing a public package with the same name as an internal package, exploiting package managers that check public registries first

  • Account takeover: Compromising a legitimate maintainer's credentials and pushing a backdoored update

  • Star-jacking: Cloning a popular repo, adding malware, and publishing under a similar name

Advanced SCA tools analyze package behavior, such as network calls, file system access, obfuscated code, and post-install scripts, to detect malicious intent even before a CVE is assigned.


8.3 The SCA Tool Landscape

Tool

Description

Strengths

Weaknesses

Snyk

Most developer-focused commercial SCA platform. It integrates with GitHub, GitLab, Bitbucket, and most CI systems. A dedicated research team curates its vulnerability database, and it provides automated fix PRs that bump vulnerable dependencies to patched versions.

Developer experience, automated fix PRs, broad language support, container scanning.

Free tier is limited, pricing scales with project count, can generate alert fatigue on large monorepos.

GitHub Dependabot

Built into GitHub and free for all repositories. It monitors your dependency manifests, creates pull requests when it finds vulnerabilities, and can also open PRs for routine version updates.

Zero setup for GitHub users, free, well-integrated with GitHub Security Advisories.

GitHub-only, limited policy controls, no reachability analysis, no license compliance.

Renovate

Open-source dependency update tool that runs as a bot on your repositories. While not a pure SCA tool, it keeps dependencies current, which is the most effective way to reduce your vulnerability surface area over time.

Highly configurable, supports every major package manager, can be self-hosted, grouping and scheduling options.

Not a vulnerability scanner - it updates dependencies but does not perform CVE matching or license analysis on its own.

OWASP Dependency-Check

Free, open-source SCA tool that identifies known vulnerabilities in project dependencies. It supports Java, .NET, Python, Ruby, Node.js, and several other ecosystems.

Free, open source, integrates with Maven/Gradle/Jenkins, maps directly to NVD data.

High false positive rate, slower database updates than commercial tools, limited support for newer ecosystems.

Rafter

Combines SCA with SAST in a single platform. It scans your dependencies alongside your source code, providing a unified view of both first-party and third-party risk.

Unified SAST + SCA, GitHub integration, actionable prioritization.

Newer platform, still expanding language coverage.

GitLab Dependency Scanning

Built into GitLab CI/CD and reports findings in merge requests, the vulnerability report, and the dependency list. Its newer SBOM-based analyzer scans all dependencies, including transitive ones, and static reachability analysis highlights which vulnerable packages the application actually imports, helping teams prioritize real exposure. Combined with GitLab's security policies, findings can block merges or require approval.

Native to GitLab CI and merge requests, CycloneDX SBOM output, reachability analysis, policy-based approvals, one platform alongside SAST, DAST, secret detection, and container scanning.

Full functionality requires the Ultimate tier, GitLab-only, reachability limited to certain languages, SBOM-based analyzer still in Limited Availability.



8.4 Integrating SCA Into Your CI/CD Pipeline


Dependency scanning delivers the most value when it runs automatically on every pull request and merge to main. Here is a reference pipeline configuration.


# Security Scan — GitLab Dependency Scanning (SCA)
# Requires GitLab Ultimate.

stages:
  - test
  - security-gate

include:
  # v2 = the SBOM-based analyzer that replaced Gemnasium.
  # On older self-managed instances without v2, use
  # `Jobs/Dependency-Scanning.latest.gitlab-ci.yml` plus
  # DS_ENFORCE_NEW_ANALYZER: "true".
  - template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml

variables:
  AST_ENABLE_MR_PIPELINES: "true"

# ---------------------------------------------------------------------------
# The scan itself. The analyzer reads package-lock.json
# straight from the repo, so the lockfile must be committed.
# ---------------------------------------------------------------------------
dependency-scanning:
  artifacts:
    expire_in: 30 days
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
    - if: $CI_PIPELINE_SOURCE == "schedule"

# ---------------------------------------------------------------------------
# The idiomatic GitLab approach is a merge request approval policy
# (Secure > Policies), which blocks the MR
# Keep this job if you want a hard pipeline failure
# as well — or delete it once the policy is in place.
# ---------------------------------------------------------------------------
sca-gate:
  stage: security-gate
  image: alpine:3.20
  needs:
    - job: dependency-scanning
      artifacts: true
  before_script:
    - apk add --no-cache jq
  script:
    - |
      REPORT=gl-dependency-scanning-report.json
      if [ ! -f "$REPORT" ]; then
        echo "No dependency scanning report found — failing closed."
        exit 1
      fi
      COUNT=$(jq '[.vulnerabilities[]? | select(.severity == "Critical")] | length' "$REPORT")
      echo "Critical vulnerabilities: $COUNT"
      if [ "$COUNT" -gt 0 ]; then
        jq -r '.vulnerabilities[]?
               | select(.severity == "Critical")
               | "\(.name) — \(.location.dependency.package.name)@\(.location.dependency.version)"' "$REPORT"
        exit 1
      fi
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
    - if: $CI_PIPELINE_SOURCE == "schedule"

# ---------------------------------------------------------------------------
# SBOM. GitLab emits CycloneDX (`**/gl-sbom-*.cdx.json`) from the scan
# job and ingests it into the Dependency List — no extra job needed for that.
# This job exists to demonstrate SPDX generation. 
# Drop it if CycloneDX is acceptable.
# ---------------------------------------------------------------------------
sbom-spdx:
  stage: security-gate
  image:
    name: cyclonedx/cyclonedx-cli:0.25.1
    entrypoint: [""]
  needs:
    - job: dependency-scanning
      artifacts: true
  script:
    - find . -name "gl-sbom-*.cdx.json" -exec cyclonedx merge --output-file merged.cdx.json --input-files "{}" +
    - cyclonedx convert --input-file merged.cdx.json --output-file sbom.spdx.json --output-format spdxjson
  artifacts:
    name: security-results
    expire_in: 90 days
    paths:
      - sbom.spdx.json
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
    - if: $CI_PIPELINE_SOURCE == "schedule"

Key points in this pipeline:

  • Fail on critical: The pipeline blocks merges when critical-severity vulnerabilities are found in dependencies. This prevents known-bad libraries from reaching production.

  • SBOM generation: A Software Bill of Materials is increasingly required by regulation (U.S. Executive Order 14028) and by enterprise customers. Generating it in CI ensures it stays current.


8.5 Building a Dependency Management Strategy


Dependency scanning is a tool, while dependency management is a strategy. The tool identifies issues; the strategy defines how you respond.


Establish a Dependency Governance Policy


Define clear rules for adding new dependencies:

  • Evaluation criteria: Maintenance activity, download counts, known vulnerabilities, license compatibility, and bus factor (how many maintainers does the package have?)

  • Approval process: Who can add a new direct dependency? For critical applications, this should require a brief review.

  • Banned packages: Maintain a list of packages your organization will not use, either for security reasons or because a preferred alternative exists.


Keep Dependencies Current


The single most effective dependency security practice is keeping packages up to date. Maintainers fix most CVEs quickly. If you are running the latest version, the window of vulnerability is minimal.

Renovate or Dependabot should run continuously, creating update PRs that your CI pipeline validates. For most packages, automatically merging patch-level updates is safe and dramatically reduces your vulnerability backlog.


Monitor Continuously, Not Just at Build Time


New CVEs are published against existing package versions every day. A clean SCA scan today does not guarantee a clean state tomorrow. Your SCA tool should:

  • Run on every PR and merge

  • Run on a daily or weekly schedule against your main branch

  • Send alerts when new CVEs affect your deployed dependencies

  • Integrate with your incident response workflow for critical findings


Generate and Maintain SBOMs


A Software Bill of Materials is a machine-readable inventory of every component in your application. It serves two purposes:

  1. Incident response: When the next Log4Shell drops, you can query your SBOM to determine exposure in seconds, not hours.

  2. Compliance: Government contracts, regulated industries, and enterprise customers increasingly require SBOMs as part of procurement.


Generate SBOMs in your CI pipeline and store them alongside your releases.


Pin Dependency Versions


Use lockfiles religiously. Never deploy from a fresh npm install that resolves version ranges at install time. Your lockfile ensures that the exact versions you tested are the exact versions you deploy.

For critical applications, consider vendoring dependencies, checking them directly into your repository or a private registry, so that even a compromised public registry cannot inject malicious code.


8.6 Common SCA Mistakes to Avoid


Scanning only direct dependencies. If your SCA tool doesn't resolve transitive dependencies, it misses most of your attack surface. Verify that your tool parses lockfiles, not just manifests.


Ignoring dev dependencies. While dev dependencies do not ship to production, they run in your CI environment. A compromised dev dependency can steal secrets from your build pipeline, modify build outputs, or exfiltrate source code.


Treating all CVEs equally. A CVSS 9.8 with a public exploit in a production dependency is not the same as a CVSS 4.0 with no known exploit in a testing utility. Prioritize ruthlessly, or your team will develop alert fatigue and start ignoring SCA results entirely.


Running SCA only in CI. Developers should see dependency vulnerability information in their IDE or during local development. Catching a vulnerable dependency before it reaches a PR saves review cycles and pipeline time.


Not tracking your SBOM. Without a current bill of materials, you cannot respond quickly to zero-day disclosures. When a new critical CVE is announced, you need to know within minutes whether any of your applications are affected.



Software Supply Chain Security with Plexteq


Plexteq helps organizations secure their software supply chain with real-time visibility into open source and third-party applications and components. By monitoring application behavior in production, Plexteq accurately identifies vulnerable or unused components, prioritizes risks based on actual usage, and delivers a real-time SBOM to help customers continuously monitor supply chain vulnerabilities. This approach reduces false positives and maintains compliance with industry standards.



FAQ


What is software composition analysis (SCA)?

Software composition analysis (SCA) is a security practice that helps you find, track, and monitor every third-party component in your codebase for known vulnerabilities, license risks, and signs of tampering. SCA creates an inventory of all your dependencies, often called a software bill of materials, and checks it against vulnerability feeds as new CVEs come out. Dependency scanning is the process used, while SCA is the broader field that includes it.

An SBOM is a compliance artifact, a file that shows what makes up an application, helping organizations find and fix security risks in all its parts.

It is the practice of protecting everything involved in building and shipping software, not only the code your team writes. That covers open-source libraries, third-party SDKs, build tools, CI/CD pipelines, registries, and deployment infrastructure, with the goal of keeping tampered or malicious code out at every step.

Attackers compromise something you already trust instead of attacking you directly. In SolarWinds, a backdoor was inserted through the vendor's build system and shipped in signed updates. In XZ Utils, an attacker spent years earning maintainer trust before planting a backdoor in a compression library that OpenSSH depended on.

All three trick a build into installing a malicious package:

  • Typosquatting uses a name that is one keystroke away from a popular package.

  • Dependency confusion publishes a public package under the name of a company's internal one.

  • Slopsquatting registers package names that AI coding tools invent, so that unverified AI-suggested dependencies resolve to the attacker's package.

No. SAST finds flaws in code you wrote, DAST tests the running application from the outside, and SCA finds known issues in code you imported. A SQL injection in your own code and the same flaw inside a library are equally exploitable, but each is caught by a different tool.

Increasingly, yes. U.S. Executive Order 14028 called for SBOMs from software suppliers, and regulated sectors such as healthcare, defense, automotive, and finance expect them. Enterprise customers also request them during procurement.

Generate it automatically in CI for every build, using tools such as Syft or CycloneDX plugins, in CycloneDX or SPDX format. Store each one in a central, immutable repository linked to its build artifact. Keep historical SBOMs too, because regulators will ask which older versions are affected by a new vulnerability.

Severity score alone is not enough, since many high-scoring CVEs are never exploited. Weigh whether an exploit is known, whether your code actually reaches the vulnerable function, whether a fix exists, and whether the dependency runs in production or only in development.

Run them on every pull request and merge, and on a daily or weekly schedule against the main branch. New CVEs are published against existing versions every day, so a clean scan today says nothing about tomorrow. Surfacing results in the IDE catches problems before they reach review.


External References


Have a question?

ENGINEERING THE FUTURE

Plexteq provides top-quality software development, testing, and support services.

​

Systems we develop deliver benefit to customers in high-tech, healthcare, telecom, retail, network security, real estate, video conferencing industries.

 

We have advanced skills and ample resources to create large-scale solutions as well as guide startups and scale-ups from idea to profit.

CONTACT US

- Ahtri tn 12, Tallinn, Estonia
- 18 Yunosti ave., Vinnytsia, Ukraine
- 275 New North Road, London, England

+372 6 10 42 43 
+380 67 395 35 34

  • Twitter
  • Facebook
  • LinkedIn

© 2014–2026 Plexteq

bottom of page