Vulnerable Components and the Software Supply Chain
CAP, ACID vs BASE, latency numbers, back-of-envelope estimation, single points of failure — the vocabulary every system designer thinks in.
Core Philosophy: Modern software is not written — it is assembled. Any application is a small amount of original code resting on a vast foundation of third-party libraries, frameworks, and tools, each written by someone else. Every one of those dependencies is code you didn’t write but you are responsible for. When one of them has a vulnerability, your application has that vulnerability — no matter how perfect your own code is.
Part 1: The Problem
Picture a typical web application. The developers wrote, perhaps, a few thousand lines of original code. But the application also includes a web framework, a templating engine, a database library, an authentication library, dozens of utility libraries — and each of those depends on others, which depend on others. The result is that the overwhelming majority of the code actually running is third-party.
This is normal, sensible, and unavoidable — nobody should rewrite a web framework from scratch. But it has a hard security consequence: you are responsible for the security of code you never wrote and may never have read. If a library three levels deep in your dependencies has a critical vulnerability, your application is critically vulnerable. This section is about that reality — the software supply chain — and how attackers and defenders deal with it.
Part 2: The Concept — Dependencies and Known Vulnerabilities
A dependency is any external piece of code your application relies on. Dependencies form a tree: your code depends on libraries (direct dependencies), which depend on other libraries (transitive dependencies), often many layers deep.
YOUR CODE
│
┌────────┼────────┐
lib A lib B lib C ← direct dependencies
│ │ │ │
libD libE libF libG ... ← transitive dependencies
│
libH ... ← deeper still
You explicitly chose A, B, C.
D through H came along for the ride —
and you're running all of them.
Now the key fact about vulnerabilities here: when a security flaw is discovered in a piece of widely-used software, it gets publicly catalogued. It’s assigned a CVE (Common Vulnerabilities and Exposures) identifier — a unique public ID for that specific vulnerability — and published in databases anyone can search.
This public cataloguing is good — it lets defenders know what to patch. But it cuts both ways: it also hands attackers a precise, searchable list of known weaknesses, often complete with technical detail and sometimes ready-made exploit code. So when a library has a known CVE, an attacker can:
- Fingerprint your app (recall 2.1) to identify the library and its version.
- Look up known CVEs for that exact version.
- Use published exploit details against you.
Using a component with a known vulnerability is therefore one of the easiest things for an attacker to exploit — the research is already done and public. This is its own OWASP Top 10 category for exactly that reason.
Part 3: The Software Supply Chain — A Broader Risk
“Vulnerable components” is the most common version of a bigger idea: software supply chain security. Your supply chain is everything and everyone involved in producing the code you run — the libraries, the tools that build it, the repositories it’s downloaded from, the maintainers who write it.
An attacker can target any link in that chain, not just exploit a known CVE. The main supply-chain attack patterns to be aware of:
- Known-vulnerable dependencies — the common case from Part 2: a library with a published CVE, left un-updated.
- Malicious packages. An attacker publishes a malicious library to a public package repository, hoping developers install it. Sometimes disguised with a name very close to a popular package (typosquatting — you typo the name and get the malicious one).
- Dependency confusion. A trick exploiting how package managers choose between public and private packages — an attacker publishes a public package with the same name as a company’s internal private one, hoping the tooling pulls the attacker’s version.
- Compromised legitimate packages. A real, trusted, popular package gets compromised — its maintainer account is taken over, or a malicious contributor sneaks code in — and a poisoned update flows out to everyone who uses it.
- Compromised build/delivery tooling. The attacker poisons the process that builds or ships the software, so even sound source code produces a malicious result.
This is also a place where the integrity half of the CIA triad (1.1) comes to the front: much of supply-chain defense is about verifying that the code you received is genuinely the code you intended — unaltered and from a trusted source. (You’ll see the integrity-verification side in Phase 4 and Phase 5B/5C.)
Part 4: Finding Vulnerable Components
The good news: detecting known vulnerable components is one of the most automatable tasks in security. The approach:
1. INVENTORY Determine what components the app uses, and
their versions. You cannot assess what you
haven't inventoried. The result is sometimes
formalized as an SBOM (see below).
2. CHECK Compare each component+version against public
vulnerability databases (CVE data).
3. AUTOMATE Use dependency-scanning / SCA tools that do
steps 1–2 automatically and continuously.
4. ASSESS For each finding: is the vulnerable component
actually used in an exploitable way? Severity
and real exposure matter, not just presence.
5. PRIORITIZE Fix by risk (recall 1.1) — exploitable +
high-impact first.
Key tools and terms:
- Software Composition Analysis (SCA) — the category of tools that inventory your dependencies and flag known-vulnerable ones. These can run automatically, including inside a CI/CD pipeline (a Phase 5B/5C topic).
- Dependency scanners — practical tools (including ones built into package managers and code-hosting platforms) that audit a project’s dependency tree against CVE data.
- SBOM (Software Bill of Materials) — a formal, complete inventory of every component in a piece of software. Increasingly expected, it makes “what are we even running?” answerable.
- Vulnerability databases — the public CVE catalogues and related scoring systems you look findings up in.
From the attacker’s side, the same information is the input: fingerprint the target (2.1), identify component versions, search the same public databases for known exploits.
Part 5: Why This Is Hard to Manage
If detection is so automatable, why do vulnerable components remain a top category? Because managing them is genuinely hard:
- Scale. A single app can have hundreds or thousands of dependencies (counting transitive ones). That’s a large, constantly-changing inventory.
- Transitive blindness. Developers know their direct dependencies but are often unaware of the deep transitive ones — yet a vulnerability anywhere in the tree counts.
- The update dilemma. Updating a vulnerable library can break the application (a newer version may change behaviour). So updates need testing, which takes effort — and so they get delayed.
- Constant churn. New vulnerabilities are disclosed every day. A dependency that’s clean today may have a critical CVE tomorrow. This is not a one-time check; it must be continuous.
- Abandoned dependencies. Some libraries are no longer maintained — when a vulnerability is found, no fix is ever coming, and the app must replace the component entirely.
- The “it works, don’t touch it” trap. Teams avoid updating dependencies for fear of breakage, and the known-vulnerable versions quietly accumulate.
The realistic takeaway: dependency security is an ongoing process, not a task you complete — which is why it belongs to vulnerability management (Phase 4.8) and to automated pipelines (Phase 5B/5C).
Part 6: A Glance at the Fix
Managing component risk (built fully in Phase 4.8 and the Phase 5 tracks):
- Maintain an inventory. Know every component you use — ideally an SBOM. You can’t secure an unknown.
- Scan continuously and automatically. Run SCA / dependency scanning regularly and as part of the build pipeline, so new CVEs in existing dependencies surface fast.
- Patch and update on a schedule. Keep dependencies current; treat updating as routine maintenance, not a scary event. Prioritize by risk.
- Minimize dependencies. Every dependency is attack surface and maintenance burden. Don’t add a library for something trivial. Fewer, well-chosen, well-maintained dependencies beat many casual ones.
- Vet what you add. Before adopting a dependency: is it actively maintained? widely used? reputable? Check the name carefully (typosquatting).
- Verify integrity. Use mechanisms that confirm a downloaded package is genuine and unaltered (checksums, lockfiles, signature verification) — the integrity principle from Part 3.
- Have a response plan. When a major CVE drops in something you use (these events happen and make headlines), you need to know you use it and be able to update fast. That speed depends on having the inventory and process already in place.
The unifying principle: you own the security of everything you ship, including the parts you didn’t write — so know what you’re running, keep it current, and keep checking.
📓 Key Terms
| Term | Plain meaning |
|---|---|
| Dependency | An external piece of code an application relies on. |
| Direct / transitive dependency | A library you chose / a library pulled in by another library. |
| CVE | Common Vulnerabilities and Exposures — a public ID for a specific known vulnerability. |
| Vulnerability database | A public catalogue of known vulnerabilities. |
| Software supply chain | Everything and everyone involved in producing the code you run. |
| Typosquatting | A malicious package named to mimic a popular one. |
| Dependency confusion | Tricking tooling into pulling a malicious public package over an internal one. |
| SCA (Software Composition Analysis) | Tools that inventory dependencies and flag known-vulnerable ones. |
| SBOM | Software Bill of Materials — a formal inventory of all components. |
🧪 Hands-On Lab
Scanning your own projects is always fine. Treat any results responsibly.
Task 1 — Inventory a real project. Take any software project you have (or download an open-source one). Find its dependency manifest (the file listing its libraries). List the direct dependencies. Then appreciate that each has its own — the real tree is far larger.
Task 2 — Run a dependency scan. Use a dependency-scanning tool on that project — many package managers have a built-in audit command, and code-hosting platforms offer automated dependency alerts. See what known-vulnerable components it reports.
Task 3 — Trace one CVE. Pick one finding from Task 2. Look up its CVE in a public vulnerability database. Read: what the vulnerability is, how severe it is, what version fixes it. You’ve just done what both a defender and an attacker do with the same data.
Task 4 — Exploit a known-vulnerable component in the lab. Deliberately vulnerable practice apps often include outdated components with known CVEs. Identify one, find its public CVE, and (in your lab) understand or carry out the known exploit. Experience how “known vulnerability” means “research already done for the attacker.”
Task 5 — Fingerprint a target’s components. On your lab app, use the fingerprinting tools from 2.1 to identify component versions from the outside — as an attacker would, with no access to the source. See how much an attacker can learn just from the app’s responses.
Task 6 — Practice the response drill. Imagine a critical CVE is announced in a popular framework. Write the steps you’d take to answer “do we use it, where, and how fast can we fix it?” Notice every step depends on having an inventory and process already in place.
⚠️ Common Mistakes
- Believing “my code is secure” means “my app is secure.” Most of the running code is third-party. Your app’s security includes every dependency.
- Ignoring transitive dependencies. The vulnerable library is often one you never chose directly. The whole tree counts.
- Treating dependency checking as one-time. New CVEs appear daily. A clean scan today says nothing about next week. It must be continuous.
- Adding dependencies carelessly. Every library is attack surface and maintenance debt. Don’t pull in a whole package for a trivial need; vet what you do add.
- Delaying updates out of fear. “Don’t touch it, it works” lets known-vulnerable versions pile up. Make updating routine and tested, not rare and scary.
- Not knowing what you run. If you can’t quickly answer “do we use library X?”, you can’t respond when X has a critical CVE. Inventory first.
✅ Recap & What’s Next
- Modern software is assembled from third-party components, so you own the security of code you never wrote — a vulnerable dependency makes your app vulnerable.
- Known vulnerabilities are publicly catalogued as CVEs — which helps defenders patch but also hands attackers a ready map; the wider software supply chain can be attacked at many links (malicious packages, typosquatting, dependency confusion, compromised updates).
- The fix is an ongoing process — inventory (SBOM), scan continuously (SCA), patch on schedule, minimize and vet dependencies, verify integrity (Phase 4.8 / Phase 5).
Next (2.11): You’ve now learned every major web vulnerability category individually. The final page of Phase 2 brings them together — a complete, methodical web application penetration test, run end to end, ending in a professional findings report.
⁂ Back to all modules