CI/CD·6 min read·

Dependency Vulnerability Scanning Integrated Into CI

Scan dependencies for known vulnerabilities in every build and gate on blocking findings to keep supply-chain risk out of production.

NB

Netbay Engineering

Netbay Engineering

On this page

Modern applications are mostly dependencies you did not write. That makes the supply chain a first-class security surface, and the place to watch it is CI: every build, a scan of the dependencies you pull, with the result gating or annotating the merge. Catching a known vulnerable package at PR time is orders of magnitude cheaper than discovering the breach in production.

What scanning actually checks

Dependency scanners compare your resolved dependency set against public vulnerability databases — the OSV, NVD, and language-specific advisories. They flag packages with known CVEs, recommend upgraded versions, and report severity. The key detail is that scanners look at the resolved lockfile, not the manifest, because the lockfile reflects what you will actually install. A manifest alone can hide a vulnerable transitive version.

Because the results are versioned (a new CVE can be published about a package you already ship), the scan should run not just on new PRs but on a schedule, so newly disclosed vulnerabilities in your existing lockfile surface promptly.

yaml
name: vuln-scan
on:
  pull_request:
  schedule:
    - cron: "0 6 * * *"
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm audit --omit=dev --audit-level=high

Running npm audit with a severity threshold means the job fails when a high-severity issue lands, forcing the resolution before merge rather than after.

Gate on blocking findings, annotate the rest

Not all findings deserve a hard stop. A pragmatic policy: block merges on critical or high severity in production dependencies, and annotate or file tickets for medium and low. This prevents the pipeline from becoming permanently red over a low-severity transitive package while still surfacing important risks. Make the policy explicit in the scan config so the gate is predictable, not surprising.

yaml
deps:
  fail-on: [critical, high]
  warn-on: [medium, low]
  exceptions:
    - advisory: "GHSA-xxxx"
      reason: "no fixed version yet; tracked in SEC-42"

Exceptions are the discipline problem. They are necessary for zero-day and un-fixed advisories, but they drift into permanent silence. Give every exception an expiry and a tracking issue, and make CI complain when the expiry lapses, much like the quarantine policy from the pipelines posts.

resolved lockfile direct + transitive advisory scan OSV + databases clean: allow merge critical/high: block every build plus a daily rescan catches new CVEs exceptions expire and are tracked

Beyond package managers: containers and the platform

The same idea extends up the stack. Scan the base image and the final container image for OS-level vulnerabilities, not just the application's language dependencies. A build that layers an application over a base image with known issues inherits them. Feeding the resolved image through a scanner in the same pipeline that builds it closes the gap between "language deps are clean" and "the thing I run is clean."

yaml
steps:
  - name: build image
    run: docker build -t app:latest .
  - name: scan image
    run: trivy image --exit-code 1 --severity HIGH,CRITICAL app:latest

Using --exit-code 1 on the severity threshold turns the image scan into a hard gate that fails the build on a high-severity finding, exactly like the lockfile scan.

The alerting loop

A gate is only useful if failures reach the right people. Wire scan results into your incident and review channels: fail the merge, page the security contact for critical findings, and file tickets automatically for the medium and low set. Otherwise the scan produces red noise that teaches the team to ignore it. Pair the tooling with a short on-call rotation for "the scan went red, settle it," so responsibility is clear and nobody owns vulnerability debt.

Treat findings as debt, not shame

Finally, a healthy culture note: a vulnerable package is not a personal failing, and the scan finding it is a success, not an accusation. The pipeline should make it easy to upgrade, not humiliating to be flagged. When the tooling is fast, the policy explicit, and exceptions expiring, the scan becomes a background safety net that almost never bites — because the dependencies it guards are kept current.

Takeaway: scan resolved dependencies and container images in every build, gate on critical and high, and expire every exception. Add it to your pipeline and host its other stages on a Netbay VPS from Lucknow DC01, spun up in under 60 seconds at netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance