Scanverra
Back to Articles
Code Quality

Automating Code Quality and Dependency Audits in CI/CD

·9 min read

Manual code review catches logic bugs and style issues. It almost never catches a dependency that quietly became vulnerable last week - that requires checking against a database that changes daily, which is exactly the kind of check that belongs in automation, not a human's memory.

Why Dependency Health Is a Security & Velocity Issue

Modern apps are mostly other people's code - a typical project pulls in hundreds of transitive dependencies most contributors have never looked at. Three things go wrong quietly over time:

  • A dependency gets a CVE disclosed after you already shipped it, and nothing tells you unless you're watching for it.
  • A package gets abandoned - no more patches, ever - and you don't find out until you need one.
  • Version drift accumulates until an upgrade that should've been a patch release becomes a multi-day migration.

None of this shows up in a normal PR review. It only shows up if something is actively checking for it, continuously.

What to Check Automatically

  • Vulnerable dependencies - known CVEs in direct and transitive dependencies, not just the top-level package.json.
  • Outdated packages - how far behind latest, and whether the gap includes a security fix.
  • License issues - a copyleft license slipping into a proprietary codebase through a transitive dependency is a real, recurring problem.
  • Code quality signals - lint violations, obvious anti-patterns, dead code - the things a reviewer would flag if they had time to look everywhere.
  • Repo hygiene - committed secrets, overly permissive CI tokens, missing branch protection.

Where This Fits in Your Pipeline

Two complementary cadences, not one or the other:

  • Pre-merge, on every PR - catches new problems before they reach main, when they're cheapest to fix and the author still has context loaded.
  • Scheduled, e.g. nightly - catches problems in code that already merged, when a new CVE gets disclosed for a dependency you added months ago and never touched again.

Pre-merge alone misses the second case entirely - most vulnerable dependencies weren't vulnerable when they were added.

A Minimal GitHub Actions Example

A scan step on every push and pull request, so results show up before code merges:

.github/workflows/audit.ymltypescript
1name: Repo Audit
2on:
3  pull_request:
4  push:
5    branches: [main]
6
7jobs:
8  audit:
9    runs-on: ubuntu-latest
10    steps:
11      - uses: actions/checkout@v4
12      - name: Run dependency & quality scan
13        run: |
14          curl -X POST https://scanverra.com/api/repo/scan \
15            -H "Authorization: Bearer ${{ secrets.SCANVERRA_API_KEY }}" \
16            -d '{"owner":"your-org","repo":"your-repo","ref":"${{ github.sha }}"}'

Turning Findings Into Action

The failure mode that kills these pipelines isn't missing checks - it's checks nobody acts on. A few things that keep it useful instead of ignored:

  • Fail the build only on high-severity, actionable findings - a pipeline that blocks on every low-severity notice trains people to ignore it entirely.
  • Warn (don't block) on everything else, surfaced somewhere visible, so it's not invisible either.
  • Triage false positives once and suppress them explicitly, rather than re-litigating the same finding every run.
  • Where possible, let AI-suggested fixes turn a finding directly into a draft PR - the gap between "flagged" and "fixed" is where most findings quietly die.

A Simple CI Checklist

  • Dependency/CVE scan runs on every PR, not just manually before releases.
  • A scheduled scan also runs against main, independent of new PRs.
  • Severity threshold for failing the build is deliberately set, not left at whatever the tool defaults to.
  • Someone is actually assigned to triage new findings - a check nobody owns is a check nobody fixes.

Automate this in your next PR

Run a free repo scan and see outdated dependencies, CVEs, and code quality issues before they ship.

Run a free repo scan