Arkendia Classrooms
Lesson 22 of 28 · 17 min

Vulnerable components and dependency management

Almost no modern application is written from scratch. A typical web project relies on a framework, dozens of libraries, and those libraries rely on others in turn, often hundreds of packages in all. You inherit the security of every one of them. When a flaw is discovered in a popular library, thousands of applications become vulnerable on the same day, including yours, even though you did not write a single line of the faulty code.

Scope reminder

Identifying that an application uses an outdated component is mostly passive and legitimate in an authorised test. Using a known weakness against a system is another matter, and requires explicit permission. Do not run public exploit code against any system you do not own or are not authorised to test. In this lesson you will focus on identifying and managing risk, which is exactly what a defender and a tester report.

The apartment-building analogy

A building shares its structure: pipes, wiring, elevators. If the supplier of the elevator discovers a defect, every building with that elevator model has to react. The owners did not manufacture the elevator, but they are responsible for their residents’ safety. For software, the “elevators” are your dependencies.

Known vulnerabilities: CVE and friends

When a security researcher or vendor discovers a flaw in a public product, it is catalogued so that everyone can refer to it unambiguously.

  • CVE (Common Vulnerabilities and Exposures): a unique identifier of the form CVE-YEAR-NUMBER for each publicly disclosed flaw. The programme is described at cve.org.
  • NVD (National Vulnerability Database): maintained by NIST, it enriches each CVE with a description, severity score, affected product versions and references, at nvd.nist.gov.
  • CWE (Common Weakness Enumeration): a catalogue of types of weaknesses (for instance “SQL injection”), useful to classify findings.
  • Vendor advisories and security bulletins, which describe fixes and workarounds.

A CVE entry tells you: what is affected, which versions, how serious it is (CVSS score, see chapter 7), and whether a fixed version exists. It is public knowledge, which cuts both ways: defenders can react, and attackers can read the same information.

How a tester identifies components

  1. Fingerprint the technologies. From headers, cookies, file paths, page source (for instance the names and version suffixes of JavaScript files), error messages, and default pages. Tools and browser extensions can help recognise common platforms.
  2. Determine the version. A version number in a file name, a header, a comment or a changelog can reveal it. Sometimes only an approximate range can be inferred.
  3. Look it up in the NVD or CVE database for known flaws in that version.
  4. Assess relevance. Not every vulnerability in a library affects the application: it may concern a feature the application does not use, or it might need specific conditions. A good report separates “vulnerable version present” from “exploitable in this context”.
  5. Report without exploiting, unless the engagement includes demonstrating impact and the client has agreed.
Component: front-end library (version taken from the script file name)
Observed version: older than the first fixed release listed in the advisory
Known issue: a published CVE affecting this version range (see nvd.nist.gov)
Context: the vulnerable feature is used by the contact page
Recommendation: upgrade to the latest supported release, test, redeploy

Why components stay outdated

  • Fear of breaking things. Upgrading may change behaviour. Without tests, teams postpone.
  • No inventory. Nobody knows exactly which components and versions are in use.
  • Transitive dependencies. The vulnerable package is not one you chose; a library you use pulled it in.
  • Abandoned projects. A library stops being maintained, so no fix will ever come.
  • Copy-pasted code and vendored files. Libraries copied directly into a project do not show up in package managers.
  • Slow patch processes in organisations with heavy approval chains.

Supply-chain risks

Beyond honest bugs, attackers also target the software supply chain: publishing malicious packages with names similar to popular ones (typosquatting), taking over the account of a maintainer, or inserting harmful code into a legitimate update. Dependencies are code that runs with your application’s privileges. Treat adding a new one as a decision, not a reflex: check that it is maintained, widely used, and necessary.

Managing dependencies well

Know what you have

Keep an up-to-date inventory, often called a software bill of materials (SBOM): a list of components and versions in each application. It lets you answer, in minutes, “are we affected by this new CVE?”. Lock files that record exact versions help ensure reproducible builds.

Scan automatically

Package managers and ecosystems offer audit commands that compare your declared dependencies against databases of known vulnerabilities. Software composition analysis (SCA) tools do this in the delivery pipeline and warn when a new vulnerable component sneaks in, or when a new CVE affects what you already use. Make failing the build on critical issues a team decision.

Update regularly and in small steps

Small, frequent updates are easier to test and less risky than rare big jumps. Automated tools can open update proposals for review. Pair them with a good test suite so that you can accept updates with confidence.

Prioritise by risk

Use the severity score, whether the component is exposed to the internet, whether the vulnerable function is used, and whether the flaw is known to be actively exploited. Public catalogues of actively exploited vulnerabilities, maintained by national agencies, help decide what to patch first.

Have a plan for the unpatchable

When no fix exists, options include removing the feature, replacing the library, adding a compensating control (such as a restriction in front of the component), or isolating it. Document the decision and review it regularly.

Reduce the surface

Fewer dependencies mean fewer problems. Remove unused libraries, avoid pulling a large package for a tiny function, and avoid shipping development tools to production.

Beyond libraries

The same thinking applies to everything the application stands on: the operating system, the runtime, the database server, the content management system and its plug-ins, container base images and third-party scripts included in your pages. Plug-ins for popular content management systems are a very common source of real-world compromises because they are numerous and unevenly maintained.

Tip

When you report an outdated component, always say which finding the version information comes from and how confident you are. A banner can be changed or can lie, and a back-ported fix may make an apparently old version safe. Honesty about certainty builds trust.

Your turn: assess a component inventory

Using your lab application (or the sample below), build a small component table: name, observed version, source of the information, whether a fix is available (look up the real project’s advisories on cve.org or nvd.nist.gov to see how an entry looks), and your recommended action. If your lab is a container or a project with a dependency file, run its ecosystem’s audit command in your own lab environment and note the output.

See a solution

A sample table you might produce:

ComponentVersion evidenceKnown issue?Action
Front-end script libraryFile name includes an old versionYes, published CVEUpgrade; test the pages that use it
Web frameworkHeader discloses the versionCheck advisories; version supportedKeep updated; hide the header
CMS plug-inListed on a public pageProject abandonedReplace with a maintained alternative

Also note the process recommendation: maintain an SBOM and scan dependencies in the build pipeline.

Key takeaways

  • Applications inherit the vulnerabilities of their frameworks, libraries and plug-ins, including transitive dependencies.
  • CVE identifies publicly known flaws; NVD adds severity and affected versions; both are public references.
  • Testers fingerprint components, look up versions, assess relevance, and report without exploiting unless explicitly authorised.
  • Defend with an inventory (SBOM), automated scanning, small regular updates, prioritisation by risk and a plan for unmaintained components.
  • Treat every new dependency as a security decision, because of supply-chain risks.

One kind of feature deserves its own lesson because it hands the server a file chosen by a stranger: file upload.

Advertisement
Log in to save your progress. Log in