So far we've reviewed our own code and configuration. But a modern application like BazarNube is, for the most part, other people's code: React, Express, dozens of npm packages, Spring and its transitive dependencies in the Java module. Each of those pieces can have known vulnerabilities (CVEs) that an attacker exploits without touching your logic. That's A06:2021 – Vulnerable and Outdated Components.

It's a peculiar category: you rarely "discover" it by auditing your code, because the flaw lives in a library. It's fought with process: inventory what you use, know which versions you have, watch the CVEs that affect them, and update in time. A single outdated transitive package —one of those you didn't even know you had— can be the way in. In this lesson we apply the software composition analysis (SCA) we already introduced in module 2 (02-05, Dependency-Check) to BazarNube's package.json and pom.xml.

Legal and ethical notice: the CVEs and versions cited are illustrative. Run the analysis only on systems and dependencies you own or have explicit authorization to test.

Contents

  1. Why dependencies are a top-tier risk
  2. Direct and transitive dependencies
  3. SCA: npm audit and OWASP Dependency-Check
  4. The SBOM: an inventory of what you assemble
  5. Version management and safe updating
  6. Supply chain risks (at a high level)
  7. Common mistakes, exercises and solutions

  1. Why dependencies are a top-tier risk

When a CVE for a popular library is published, the flaw becomes public and, often, so does how to exploit it. From that moment there's a race: attackers scan the internet for applications still using the vulnerable version. Historical cases (like that of a serialization library or of a widely used web framework) have caused massive breaches simply because victims didn't update in time.

Making it worse:

  • Third-party code is usually the bulk of the application.
  • Many dependencies are transitive (dependencies of your dependencies): you don't even know they're there.
  • Updating is "scary" (it might break something), so it gets postponed.

  1. Direct and transitive dependencies

flowchart TD
  A[BazarNube API] --> B[express]
  A --> C[a utility library]
  C --> D[transitive dependency]
  D --> E[CVE here]

Your package.json lists the direct dependencies, but the real tree (in package-lock.json) includes hundreds of transitive packages. The vulnerability is usually in a transitive one you never consciously chose. That's why "reviewing what I installed" isn't enough: you need tools that walk the entire tree.

  1. SCA: software composition analysis

SCA (Software Composition Analysis) compares your dependency tree against databases of known vulnerabilities and tells you which of your versions are vulnerable.

In the Node world: npm audit

# Checks the full tree against the npm advisory database
npm audit
# Sample output (illustrative):
#   package-x  <1.4.2  Severity: high  Prototype Pollution  (transitive of utility-library)
#   fix available via `npm audit fix`

npm audit walks package-lock.json, flags severity, and often offers npm audit fix to automatically update to a patched version. Integrate it into CI: for example, fail the build if there are high or critical vulnerabilities.

# In CI: fail if there are high-severity or higher vulnerabilities
npm audit --audit-level=high

In the Java world (and cross-platform): OWASP Dependency-Check

We already introduced it in 02-05. It analyzes the pom.xml (and .jar files) against the public vulnerability database (NVD) and reports the CVEs affecting your dependencies:

<!-- pom.xml: OWASP Dependency-Check plugin in BazarNube's Java module -->
<plugin>
  <groupId>org.owasp</groupId>
  <artifactId>dependency-check-maven</artifactId>
  <configuration>
    <failBuildOnCVSS>7</failBuildOnCVSS>  <!-- fail if there's a CVE with CVSS >= 7 -->
  </configuration>
</plugin>

failBuildOnCVSS turns the finding into a build failure, forcing you to address serious vulnerabilities before deploying. There are commercial and open source equivalents (Snyk, Trivy, Grype), but Dependency-Check is the reference OWASP project.

Tool Ecosystem Use in BazarNube
npm audit Node/JS React front + Express API
OWASP Dependency-Check Java/cross-platform Legacy module (pom.xml) and images
Image scanner (Trivy/Grype) Docker Container layers (links to A05)

  1. The SBOM: an inventory of what you assemble

An SBOM (Software Bill of Materials) is the "ingredient list" of your software: which components and exact versions make it up. It's the foundation for responding quickly to a new CVE: when "critical vulnerability in library X version Y" appears, with an SBOM you know instantly whether BazarNube uses it and where.

# Generate an SBOM in a standard format (CycloneDX) for the Node API
npx @cyclonedx/cyclonedx-npm --output-file bazarnube-sbom.json

Standard formats like CycloneDX or SPDX let you exchange the SBOM with customers and tools. Generating it on each build and archiving it gives you traceability: you know exactly what made up each deployed version.

  1. Version management and safe updating

The goal isn't "always be on the latest version at any cost", but to maintain a controlled process:

  1. Pin versions (lockfiles: package-lock.json, pom.xml with concrete versions) for reproducible builds.
  2. Automate update notices (Dependabot, Renovate) that open PRs when new versions or security patches are available.
  3. Test before updating: a good test suite lets you update with confidence; without tests, updating is scary and gets postponed (the root of the problem).
  4. Prioritize by risk: first the high/critical severity CVEs and those exploitable in your context.
  5. Remove what you don't use: every leftover dependency is attack surface. Less is more.
Strategy Benefit
Lockfiles Reproducible builds, no surprises
Dependabot/Renovate Security patches as automatic PRs
Solid tests Update without fear
Prune dependencies Less surface, less CVE noise

  1. Supply chain risks (at a high level)

Beyond "using versions with CVEs", there's the risk that the dependency itself is malicious or tampered with: packages with names similar to legitimate ones (typosquatting), compromised maintainer accounts that publish backdoored versions, or dependencies that "suddenly" change owners. High-level good practices:

  • Verify the integrity of what you download (lockfiles store hashes; don't ignore them).
  • Be wary of unmaintained dependencies, those with very few uses, or of dubious origin.
  • Restrict where packages are installed from (internal registry/proxy).

Verifying the integrity of artifacts and of the pipeline is so important that it has its own category: A08 (Software and Data Integrity Failures), which we'll see in lesson 03-10. Here it's enough to keep in mind that "secure components" also includes their provenance.

Common Mistakes and Tips

  • Ignoring transitive dependencies. That's where most CVEs live; use SCA that walks the whole tree.
  • Not integrating SCA in CI. A manual audit nobody runs doesn't protect; automate it and fail the build.
  • Updating without tests. Without a safety net, updating gets postponed forever.
  • Accumulating dependencies you don't use. Each is surface; prune periodically.
  • Having no inventory (SBOM). Facing a new CVE, you'll take days to know whether it affects you.
  • Blindly trusting any package. Watch provenance and maintenance (supply chain).
  • Tip: define a clear policy ("we don't deploy with an open critical CVE") and automate it; turn dependency security into part of the normal flow, not a sporadic heroic task.

Exercises

Exercise 1. npm audit reports a high vulnerability in a package that turns out to be transitive of a library you do use directly. The direct library hasn't yet published a version that updates that transitive. What are your options?

Exercise 2. Why does an SBOM speed up the response when a critical CVE is published in a heavily used library?

Exercise 3. A colleague proposes removing npm audit from CI "because it sometimes fails the build over vulnerabilities that don't affect us". What better alternative would you propose?

Solutions

Solution 1. Options, from most to least preferable: (a) update the direct library if it publishes a fix; (b) force the patched version of the transitive via overrides (npm) or resolutions; (c) if there's no patch, assess the real risk (is it exploitable in your usage?), apply mitigations and monitor; (d) as a last resort, replace the direct library with another maintained one. Document the decision in the backlog.

Solution 2. Because the SBOM is an exact inventory of deployed components and versions: instead of manually investigating each service, you look up the affected library and version in the SBOM and immediately know whether and where you're exposed, prioritizing patching. It reduces the response time from days to minutes.

Solution 3. Don't remove it, calibrate it: set --audit-level=high (or critical) so it doesn't block over minor vulnerabilities, and handle false positives or non-exploitable CVEs through documented, review-dated exceptions (temporary allowlist), rather than disabling the whole check. That keeps the protection without unjustified friction.

Conclusion

A06 isn't solved with a coding technique but with process discipline: inventory (SBOM), analyze composition (npm audit, Dependency-Check) automatically in CI, update with a test safety net, prune the unnecessary, and watch provenance. In BazarNube, integrating SCA into the pipeline turns CVEs into routine backlog tasks instead of incidents.

Backlog entry — A06: npm audit --audit-level=high in the CI of the front and the API; Dependency-Check with failBuildOnCVSS=7 in the Java module; Dependabot enabled; CycloneDX SBOM generated per build; pruning unused dependencies still pending.

We've secured who accesses, what's protected, how injection works, how it's designed, how it's configured, and which components we use. Time to return to a fundamental control we left pending when we distinguished it from authorization: authentication. The next lesson is A07:2021 – Identification and Authentication Failures, with BazarNube's login and sessions.

OWASP Course: Guidelines and Standards for Web Application Security

Module 1: Introduction to OWASP

Module 2: Main OWASP Projects

Module 3: OWASP Top Ten 2021 in Depth

Module 4: OWASP ASVS (Application Security Verification Standard)

Module 5: OWASP SAMM (Software Assurance Maturity Model)

Module 6: OWASP ZAP (Zed Attack Proxy)

Module 7: Best Practices and Recommendations

Module 8: Practical Exercises and Case Studies

Module 9: Assessment and Certification

© Copyright 2026. All rights reserved