In short
- CVE scanners only know published advisories. Catching malicious packages needs behaviour analysis such as Socket, plus a release-age delay.
- OSV-Scanner, Trivy, Grype and Syft are free and open source. Trivy also scans containers and IaC; Syft builds the SBOM you keep.
- Pin every GitHub Action to a commit SHA. In March 2026 attackers rewrote 76 of 77 trivy-action tags to steal CI secrets.
On this page
Nearly every team ships code with third-party packages and containers, and wants a dependency security setup that catches real problems without burying the team in pull requests. The tools here are Dependabot, Renovate, OSV-Scanner, Trivy, Grype and Syft, Snyk Open Source, Socket, npm audit and pip-audit. You get what each one actually detects, working CI snippets, a comparison table and a layered setup you can copy.
All prices and free-tier limits were checked on 11 November 2026 against vendor pages.
Three different problems, three kinds of tool
“Dependency scanning” covers three separate jobs. Most confusion, and most gaps, come from treating them as one.
1. Known vulnerabilities (software composition analysis, SCA). A scanner reads your lockfile or container image, lists every package and version, and matches them against advisory databases such as OSV.dev or the GitHub Advisory Database. It finds an old library version with a published CVE. It cannot find anything that has not been reported yet.
2. Malicious packages. A package that was published to steal credentials has no CVE when it lands. It is new, or a hijacked maintainer pushed a bad version an hour ago. Finding it needs behaviour analysis: does this version suddenly run an install script, open network connections, read environment variables or ship obfuscated code?
3. Inventory (SBOM). A software bill of materials records exactly what went into a build, in SPDX or CycloneDX format. It does not find anything on its own. It lets you answer “are we affected?” in minutes when the next advisory drops, without rebuilding old releases.
The npm worm known as Shai-Hulud shows why the second category matters. On 23 September 2025, CISA reported that this self-replicating worm had compromised over 500 npm packages and advised organisations to review dependencies and rotate developer credentials. A CVE scanner run the morning a poisoned version was published would have passed it.
From incident response and malware recovery work, the first question after a compromise is always “what exactly was running, and since when?” SBOMs and pinned versions are how you answer it quickly.
Keeping dependencies current: Dependabot and Renovate
Update bots are not scanners, but they decide how quickly a fix reaches production, and how quickly a bad release reaches you.
Dependabot
Dependabot is built into GitHub. GitHub’s plans page lists the dependency graph and Dependabot version and security updates as included on the Free plan, private repositories too. Configuration lives in .github/dependabot.yml:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 5
groups:
npm-minor-and-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
Two settings matter for supply-chain risk. cooldown delays version updates for a set number of days after a release, and GitHub’s docs are clear that it never delays security updates. groups folds minor and patch bumps into one pull request, which keeps reviewers reading them instead of rubber-stamping fifteen.
Renovate
Renovate is open source (AGPL-3.0) and runs on GitHub, GitLab, Bitbucket, Azure DevOps, Gitea, Forgejo and more. The hosted Mend Renovate app is free for public and private repositories, or you can self-host it from the npm package, a container image or the renovatebot/github-action Action. Its configuration is more flexible than Dependabot’s, which matters in monorepos.
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"osvVulnerabilityAlerts": true,
"packageRules": [
{
"matchDatasources": ["npm"],
"minimumReleaseAge": "3 days"
}
]
}
minimumReleaseAge makes Renovate wait before proposing an update. Renovate’s docs recommend 3 days for npm, because npm packages under 72 hours old can still be unpublished. osvVulnerabilityAlerts raises fix pull requests from the OSV database, though only for direct dependencies. On GitHub, Renovate can also read Dependabot alerts through vulnerabilityAlerts.
Pick one bot per repository. Running both produces duplicate pull requests.
Scanning for known vulnerabilities
OSV-Scanner
Google’s OSV-Scanner (Apache-2.0) is the official front end to OSV.dev. Version 2 uses subcommands:
osv-scanner scan -r ./
osv-scanner scan -L package-lock.json --format json
osv-scanner scan image my-app:latest
osv-scanner fix -M package.json -L package-lock.json
The fix command is guided remediation. Its docs warn that it can run package manager scripts and contact external registries, so only run it on code you trust.
Google publishes reusable workflows for GitHub Actions, one for pull requests and one for scheduled scans. The pull request version:
name: OSV-Scanner PR scan
on:
pull_request:
branches: [main]
merge_group:
branches: [main]
permissions:
actions: read
security-events: write
contents: read
jobs:
scan-pr:
uses: "google/osv-scanner-action/.github/workflows/[email protected]"
The scheduled variant uses [email protected] on a weekly cron, which catches advisories published after code merged.
Trivy
Trivy (Apache-2.0) is the widest scanner here. It scans container images, filesystems, remote Git repositories, VM images and Kubernetes, and looks for known CVEs, IaC misconfigurations, secrets and software licences. It also generates SBOMs.
trivy image python:3.12-alpine
trivy fs --scanners vuln,secret,misconfig ./
trivy config ./terraform
That breadth makes Trivy the default choice for teams that ship containers and Terraform.
It also makes Trivy a target. On 19 March 2026, an attacker used compromised credentials to publish a malicious Trivy v0.69.4 and force-push 76 of 77 version tags of aquasecurity/trivy-action to credential-stealing commits. The exposure window for the Action was about 12 hours. Aqua’s advisory (CVE-2026-33634) tells affected users to treat every secret available to those pipelines as exposed and rotate it, and to pin Actions to full commit SHAs. Version tags are mutable. Commit SHAs are not.
So pin it, with the version as a comment for readability. ed142fd is the commit behind v0.36.0 as of 11 November 2026:
- name: Scan image
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: "ghcr.io/my-org/my-app:${{ github.sha }}"
format: "table"
exit-code: "1"
ignore-unfixed: true
vuln-type: "os,library"
severity: "CRITICAL,HIGH"
- name: Scan Terraform and Kubernetes manifests
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
scan-type: "config"
hide-progress: true
format: "sarif"
output: "trivy-results.sarif"
exit-code: "1"
severity: "CRITICAL,HIGH"
The same lesson applies to every Action in this article. Dependabot’s github-actions ecosystem, shown earlier, can propose updates to your Actions, so pinning does not have to mean freezing.
Grype and Syft
Anchore’s pair splits the job in two, both Apache-2.0. Syft builds the SBOM; Grype matches it against vulnerability data.
syft ghcr.io/my-org/my-app:1.4.0 -o spdx-json=./spdx.json -o cyclonedx-json=./cdx.json
grype sbom:./spdx.json --fail-on high -o sarif
--fail-on sets exit code 2 when a finding meets the threshold. Grype also supports OpenVEX to filter out vulnerabilities you have shown are not exploitable, and prioritises findings with EPSS, CISA KEV and risk scoring.
The workflow that pays off: generate an SBOM for every release, store it beside the artefact, and rescan stored SBOMs on a schedule. When a new CVE lands, you scan last month’s SBOMs without rebuilding last month’s images.
- name: Create SBOM
uses: anchore/sbom-action@v0
with:
format: spdx-json
- name: Scan SBOM
uses: anchore/scan-action@v7
with:
sbom: "${{ github.event.repository.name }}-sbom.spdx.json"
fail-build: true
severity-cutoff: high
Those are the tags in Anchore’s README. The README itself recommends pinning to a full commit SHA for production workflows.
Snyk Open Source
Snyk Open Source adds Snyk’s own vulnerability database and remediation advice, and fits teams already using Snyk Code or Container.
snyk test --all-projects --severity-threshold=high --fail-on=upgradable
snyk monitor --all-projects
--fail-on=upgradable fails only when a fix is available, which keeps the build from blocking on problems nobody can fix today. snyk monitor takes a snapshot and creates a project in Snyk that is continuously monitored for open source vulnerabilities and licence issues. The Free plan lists 200 Open Source tests, with 5 projects. The Team plan is listed as starting at $25 a month, billed monthly, for teams of up to 10 developers.
npm audit and pip-audit
The built-in tools are free, already installed, and good enough for a first gate.
npm audit --audit-level=high --omit=dev
npm audit signatures
pip-audit -r requirements.txt --vulnerability-service osv --strict
pip-audit -r requirements.txt --format cyclonedx-json
npm audit sends a description of your dependency tree to the registry and exits non-zero at or above --audit-level. npm audit signatures checks registry signatures and provenance attestations of what you downloaded, which is a cheap integrity check worth adding to CI. pip-audit is maintained by PyPA, uses PyPI’s advisory data by default, can use OSV instead, and can emit a CycloneDX SBOM. Its Action is pypa/[email protected].
Catching malicious packages: Socket and release-age delays
Socket
Socket analyses what a package version does, rather than only checking whether it has an advisory. The Socket GitHub App watches manifests and lockfiles, and comments on a pull request when a new dependency brings known malware, an install script, a likely typosquat, obfuscated code, or new use of shell, network, filesystem or environment variable APIs.
Socket Firewall Free (sfw) blocks confirmed malware at install time. It needs no API key:
npm i -g sfw
sfw npm ci
sfw pip install -r requirements.txt
It blocks packages verified as malicious through human review, warns but does not block on AI-detected suspects, and does not block unknown or unscanned versions. It covers npm, yarn, pnpm, pip, uv and cargo. Clear the package manager’s cache first, because cached packages never cross the network for sfw to inspect.
Socket’s Free plan includes 1 developer seat, 1,000 scans a month and unlimited repositories. Team is $25 per developer seat a month from 5 seats, and Business is $50 per seat from 20 seats.
Release-age delays
The cheapest malware defence is waiting. pnpm’s docs say “in most cases, malicious releases are discovered and removed from the registry within an hour”, and package managers now support a minimum age:
# pnpm-workspace.yaml: minimum age in minutes (pnpm's docs list 1440 as the default)
minimumReleaseAge: 1440
# .npmrc: npm's min-release-age is in days
min-release-age=3
Combine this with Dependabot’s cooldown or Renovate’s minimumReleaseAge so the bot does not propose a version the package manager will refuse. Exempt your own internal packages with minimumReleaseAgeExclude (pnpm) or min-release-age-exclude (npm).
Comparison
| Tool | Detects | Targets | Cost | Best use |
|---|---|---|---|---|
| Dependabot | Outdated and vulnerable versions, via update PRs | GitHub repos | Included on GitHub Free | Default update bot on GitHub |
| Renovate | Outdated versions, OSV and GitHub alerts | GitHub, GitLab, Bitbucket, Azure DevOps and more | Free (AGPL-3.0, free hosted app) | Monorepos, non-GitHub hosts |
| OSV-Scanner | Known CVEs, licences | Lockfiles, source, container images | Free (Apache-2.0) | PR and scheduled SCA |
| Trivy | CVEs, IaC misconfig, secrets, licences, SBOM | Images, filesystems, repos, VMs, Kubernetes | Free (Apache-2.0) | Containers and IaC |
| Syft and Grype | SBOM generation, CVEs with EPSS and KEV | Images, directories, SBOMs | Free (Apache-2.0) | SBOM-first pipelines |
| Snyk Open Source | CVEs with fix advice | Manifests across ecosystems | 200 tests free; Team from $25/month | Teams on Snyk already |
| Socket | Malware, install scripts, typosquats, risky APIs | npm, PyPI, cargo and more | Free for 1 seat; Team $25/seat/month | Malicious package defence |
| npm audit | Known CVEs, signatures, provenance | npm | Free | Baseline gate for Node |
| pip-audit | Known CVEs, CycloneDX output | Python environments, requirements | Free (Apache-2.0) | Baseline gate for Python |
A layered setup
This is the setup I would put in front of a small team. Most layers cost nothing; the paid exceptions are Socket beyond one seat and dependency review on private repositories.
- Commit lockfiles and install with them.
npm ci,pnpm install --frozen-lockfileor hashedpiprequirements. Nothing else works without this. - One update bot. Dependabot on GitHub, Renovate elsewhere. Group minor and patch updates, set a cooldown of 3 to 7 days, and include the
github-actionsecosystem. - A release-age delay in the package manager so a manual install cannot pull a version from an hour ago.
- A pull request gate. OSV-Scanner’s PR workflow, or GitHub’s dependency review action (free on public repositories; private ones need GitHub Code Security). Fail on high and critical findings that have a fix.
- Malicious package detection. The Socket GitHub App on pull requests and
sfwin front of CI installs. - Build time. Syft SBOM for every image, Trivy or Grype on the image, and
trivy configon Terraform and Kubernetes manifests. - Scheduled rescans of
mainand stored SBOMs, daily or weekly, so new advisories reach you without a code change. - Pin every Action to a commit SHA and give each workflow the narrowest
permissionsblock. Keep deploy secrets out of jobs that install dependencies.
The same layers work on GitHub Actions, GitLab CI and Jenkins, which I use day to day; CI/CD tools compared covers the platform differences. For code-level scanning to pair with it, see SAST tools compared.
Layered setup checklist
- Understand the split: SCA finds published CVEs, behaviour analysis finds malware, SBOMs record what shipped.
- Dependabot or Renovate, grouped updates, cooldown set, Actions ecosystem included.
minimumReleaseAge(pnpm) ormin-release-age(npm) configured.- OSV-Scanner or dependency review on every pull request, failing on fixable high and critical issues.
- Socket App on pull requests,
sfwon CI installs. - Syft SBOM per release, scanned by Grype or Trivy, rescanned on a schedule.
- Trivy on images and IaC.
- Every third-party Action pinned to a full commit SHA, with least-privilege
permissions.
Sources
- Widespread Supply Chain Compromise Impacting npm Ecosystem (CISA) cisa.gov
- Configuring Dependabot version updates (GitHub Docs) docs.github.com
- Dependabot options reference (GitHub Docs) docs.github.com
- GitHub Security plans and pricing github.com
- actions/dependency-review-action (GitHub) github.com
- Renovate documentation docs.renovatebot.com
- Renovate configuration options docs.renovatebot.com
- Mend Renovate app (GitHub Marketplace) github.com
- OSV-Scanner usage (Google) google.github.io
- OSV-Scanner GitHub Action (Google) google.github.io
- aquasecurity/trivy (GitHub) github.com
- aquasecurity/trivy-action (GitHub) github.com
- Trivy ecosystem supply chain temporarily compromised (GHSA-69fq-xp46-6x23) github.com
- anchore/syft (GitHub) github.com
- anchore/grype (GitHub) github.com
- Grype CLI reference (Anchore) oss.anchore.com
- anchore/scan-action (GitHub) github.com
- snyk test (Snyk CLI docs) docs.snyk.io
- Snyk plans and pricing snyk.io
- Socket for GitHub (Socket docs) docs.socket.dev
- Socket Firewall Free (Socket docs) docs.socket.dev
- Socket pricing socket.dev
- npm audit (npm Docs) docs.npmjs.com
- npm config: min-release-age (npm Docs) docs.npmjs.com
- pnpm settings: minimumReleaseAge (pnpm Docs) pnpm.io
- pypa/pip-audit (GitHub) github.com