Library Vulnerability Scanning with OWASP Dependency-Check: Don’t Let It Backfire

Security tutorial - IT technology blog
Security tutorial - IT technology blog

When Your Source Code is Clean, but the Dependencies Aren’t

About two years ago, I was working on a Fintech project for a major bank. The entire team was extremely confident because our code coverage was over 90%, and we had passed every Unit Test and Code Review. However, right before the release date, the Security department sent back a report “glowing red” with over 40 critical vulnerabilities.

The irony was that none of the bugs were in the code we wrote. They were all hidden deep within open-source libraries. Some packages were “dependencies of dependencies” (transitive dependencies) that the team didn’t even know existed.

A classic example is the infamous Log4j vulnerability; even if you weren’t using it directly, another logging library might have pulled it in. At that time, our team had to stay up for 48 hours straight to audit and upgrade everything. The lesson was clear: controlling your source code isn’t enough; you must control your Software Supply Chain.

Why Do We Often Overlook Open-Source Libraries?

In modern projects, up to 80% of the actual source code is “borrowed” from third-party packages. With just a single npm install or pip install command, you are bringing thousands of lines of foreign code into your system.

Risks usually come from three directions:

  • Complacency: Absolute trust in libraries with millions of downloads.
  • Transitive Dependencies: You install library A, A pulls in B, and B contains a vulnerability in C.
  • Security Debt: Hesitating to update for fear of breaking the system, leading to the use of versions that are 3-4 years out of date.

Manually searching on the CVE website is an impossible task when the number of libraries reaches hundreds. That’s when OWASP Dependency-Check becomes an essential assistant.

Comparing Popular SCA Solutions

Before settling on a solution, I carefully considered several candidates:

  • Snyk: Great interface, detailed reports. However, the free version only allows limited scans (about 200/month), which isn’t suitable for teams running continuous CI/CD.
  • GitHub Dependabot: Convenient because it’s built-in, but it only scans code on GitHub. If you use GitLab Self-managed or Bitbucket, you’re out of luck.
  • NPM Audit: Fast but limited to the Node.js ecosystem.

OWASP Dependency-Check wins because it is completely free and part of the reputable SCA (Software Composition Analysis) project. It scans based on the NVD (National Vulnerability Database) and supports multiple languages from Java and .NET to Python and Node.js.

Real-world Implementation

Here is how I quickly configure it for the three most common environments.

1. Java Project (Maven)

You only need to declare the plugin in the pom.xml file. No cumbersome installation on the operating system is required.

<plugin>
    <groupId>org.owasp</groupId>
    <artifactId>dependency-check-maven</artifactId>
    <version>12.1.0</version>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Run the command mvn verify to view the HTML report in the target directory.

2. Node.js & Python Projects (Using Docker)

Instead of installing Java to run Dependency-Check, I usually use Docker for convenience. This keeps the dev environment clean.

docker run --rm \
    -e USER_ID=$(id -u) \
    -v $(pwd):/src \
    -v "$HOME/odc-data:/usr/share/dependency-check/data" \
    owasp/dependency-check --project "MyProject" --scan /src

CI/CD Integration: Stopping Vulnerabilities at the Gateway

Don’t wait until you’re about to release to scan. Make it a gatekeeper in your pipeline. If a High severity bug (CVSS >= 7.0) is detected, the pipeline should fail immediately.

Important Note: NVD has now implemented rate limits. You must register for a free NVD API Key to ensure scans are not interrupted.

# GitHub Actions Example
- name: OWASP Dependency Check
  uses: dependency-check/Dependency-Check-Action@main
  with:
    project: 'FintechApp'
    path: '.'
    format: 'HTML'
    args: >
      --failOnCVSS 7
      --nvdApiKey ${{ secrets.NVD_API_KEY }}

Hard-earned Lessons from Production

When deploying this at scale for a team, I’ve identified 3 key points:

  • Cache Optimization: The NVD database is about 250MB+. If you don’t cache the data directory in CI/CD, every build will take an extra 5-10 minutes just to download data.
  • Handling False Positives: Tools sometimes misidentify things (e.g., an internal library with the same name as a vulnerable package). Use a suppression.xml file to remove false alarms after careful review.
  • Prioritization: Don’t try to fix 100% of every Low/Medium bug if resources are limited. Focus on vulnerabilities with a CVSS score of 7.0 or higher first to ensure core security.

Proactively securing your supply chain is the cheapest way to protect your product. I hope this article helps you feel more confident in managing project libraries. Happy bug fixing!

Share: