If you’re building software, you’re likely using packages, libraries, containers, or other dependencies maintained by someone else. That convenience comes with a cost. Any weakness in the software supply chain is a potential path for compromise. Attackers exploit this growing web of third-party code, public registries, and automated build pipelines that make up the modern development stack. And because the code you depend on isn’t yours, these weaknesses are harder to find and fix. Supply Chain Security is the practice of understanding and remediating those security issues. If your application depends on external code, your security does too. In this article, we’ll explore what supply chain security actually means. First, we’ll look at how third-party code becomes part of your application. Then, we’ll examine the risks—from known vulnerabilities to dependency confusion. Finally, we’ll walk through how modern tools like Semgrep Supply Chain can help you detect, prioritize, and fix issues in your third-party codebase.Documentation Index
Fetch the complete documentation index at: https://docs.semgrep.dev/llms.txt
Use this file to discover all available pages before exploring further.
What is supply chain security?
Supply chain security refers to securing all the components that contribute to building and running your software. This includes third-party libraries, system packages, build tools, container images, and the registries they come from. We use these components to speed up development, but in doing so, we inherit their bugs and vulnerabilities. To manage that risk, organizations rely on a practice called Software Composition Analysis (SCA). SCA tools examine which packages your application uses, what known issues exist in those packages, and whether those issues affect your code in practice. A good SCA tool doesn’t just surface a list of CVEs (Common Vulnerabilities and Exposures), it helps you triage, prioritize, and fix them. SCA tools commonly encompass security, software licensing compliance, reliability, and more. The challenge with supply chains is that dependency graphs are complex. Most modern apps don’t just include a few libraries, they include hundreds. Many of those are transitive dependencies: code that your code relies on indirectly, through other packages. These transitive dependencies often go unnoticed, but they carry just as much risk because the impacts of a compromise can be exponential. Dependencies are commonly managed through two key files:- Manifest files describe which packages your application needs. This includes files like JavaScript’s package.json or Python’s requirements.txt.
- Lockfiles record exactly which versions of dependencies were installed, including transitive dependencies. This includes files like Yarn’s yarn.lock or NPM’s package-lock.json.
Why supply chain vulnerabilities matter
When a vulnerability is found in a package you use, your first question is usually: “Is this actually a problem for me?” That’s where reachability and exploitability come in.What is reachability?
A vulnerable function might exist in a library, but if your code never calls that function, it’s not reachable. Similarly, even if your code does call it, proper input validation or authentication checks might mean it’s not exploitable. Understanding this difference is critical for prioritizing what to fix first. This is what makes SCA challenging. Most tools will tell you what’s vulnerable, but not whether it matters. That’s why many security engineers spend hours manually investigating vulnerabilities. They look for references in the code, study input and output patterns, and try to reproduce exploits. When you’re dealing with hundreds of packages, this manual triage doesn’t scale very well. Reachability is purely hypothetical; even if a vulnerability is reachable, it may not actually be exploitable. Exploitability is a practical assessment because user input might be properly sanitized, access controls may block entry points, etc.
Real-world risks in the software supply chain
Let’s look at some of the ways supply chain vulnerabilities show up in practice.Known vulnerabilities in dependencies
These are the classic CVE-style issues. An old version of a library has a known bug—like a command injection or path traversal—and your application still uses that version. This is surprisingly common, and usually easy to fix once identified.Dependency confusion
If your internal package shares a name with a public package, and your build system pulls from the public registry first, an attacker can publish a malicious version and have it installed instead. This risk is higher in large organizations with a mix of public and private libraries.Typosquatting and malicious packages
Sometimes attackers upload packages with names that look similar to popular ones (like react1 instead of react). Other times, they intentionally submit useful-looking packages that also include malicious code. These packages can sometimes go unnoticed until they’re already used.Insecure registries and build systems
Even if your dependencies are safe, if you fetch them over insecure channels, or if your CI/CD pipeline isn’t locked down, attackers can inject malicious code during builds or deployment. A package registry is a service used for distributing software dependencies. Each programming language typically has its own registry.- CPAN for Perl
- NPM for Javascript
- PyPi for Python
- RubyGems for Ruby
- Packagist for PHP
- and many more
Detect and prioritize supply chain issues
To reduce your security risks, the first step is visibility. You need to know which packages are part of your application, what versions you’re using, and whether any of those versions are vulnerable. Tools like Semgrep Supply Chain can scan your lockfiles and give you a detailed inventory. From there, modern SCA goes further. Using static code analysis, you can discover whether vulnerable functions are actually used by your code. That is, whether the vulnerability is reachable. This helps triage issues more efficiently and respond to vulnerabilities that matter most. For example, suppose the JavaScript librarylodash has a vulnerability in a rarely used function. If you don’t call that function, the vulnerability isn’t reachable. If you do, and user input reaches it, that’s a different story.
Traditional SCA tools stop at flagging the version. But with reachability analysis, you can decide whether to fix the issue immediately, deprioritize it, or take compensating actions.