GitHub's Dependency Review runs on every pull request that touches a manifest file and flags dependencies the PR is adding, including their licenses and known vulnerabilities. Turning it on takes five minutes. Turning it on correctly, with policies that match your actual risk appetite, takes a bit more thought. This tutorial walks through enabling Dependency Review on a public or private repository, configuring the Action to fail PRs for specific severity and license conditions, and writing an override process for the handful of legitimate cases where a flagged PR must still merge.
Prerequisites: A GitHub repository you own or admin, GitHub Actions enabled, and for private repos, GitHub Advanced Security or a GitHub Enterprise Cloud plan that includes dependency review. Time to complete: About 20 minutes.
What does Dependency Review actually check?
Dependency Review compares the dependency graph of the base branch against the head branch of a PR and surfaces three things: newly added direct and transitive dependencies, their licenses, and any GitHub Advisory Database entries (GHSA) against the versions being added. For public repos, the data comes from GitHub's own dependency graph. For private repos, it requires the dependency graph feature to be enabled, which in turn requires GitHub Advanced Security on private repos or the standard free tier on public repos.
Enable the dependency graph under Settings → Code security and analysis → Dependency graph. Once it is on, the Dependency Review API becomes available for the Action to consume.
How do I add the Dependency Review Action to my workflow?
Create .github/workflows/dependency-review.yml:
name: Dependency Review
on:
pull_request:
branches: [main]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v4
with:
fail-on-severity: high
comment-summary-in-pr: always
license-check: true
vulnerability-check: true
deny-licenses: AGPL-3.0, GPL-3.0, SSPL-1.0
Commit and open a PR that changes package.json or an equivalent manifest. The Action runs against the PR's dependency diff. If the PR introduces an AGPL-3.0 licensed package or a high-severity vulnerability, the Action exits non-zero and comments a summary in the PR conversation tab.
Pin the Action to a full SHA rather than a tag for production use:
- uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.1.3
The SHA pin protects you from a compromised Action release overwriting the tag. This is cheap insurance.
How do I configure license and severity policies well?
Start permissive, tighten over time. A reasonable starting configuration fails on critical severity only, blocks the strong copyleft licenses that conflict with most proprietary products, and allows everything else through with a comment:
with:
fail-on-severity: critical
deny-licenses: AGPL-3.0, AGPL-3.0-only, AGPL-3.0-or-later, SSPL-1.0
comment-summary-in-pr: always
After two weeks of running with comments only, look at the PR history and count how many real blockers you would have had. If that number is small and well-understood, tighten to high. After another two weeks, consider moderate for production branches.
For license enforcement, prefer allow-licenses over deny-licenses once your team has the muscle built:
with:
allow-licenses: MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, Unlicense, CC0-1.0
Allow-listing forces every new license into an explicit decision, which catches the rare weird license that is not on the deny list but still should not be in the product.
How do I handle the legitimate overrides?
Real projects have cases where a flagged PR must still merge: a documented GHSA with no exploit path, a license that is acceptable for a specific carve-out, or a dependency update that brings a fix for a different, more pressing vulnerability. Handle overrides with an .github/dependency-review-config.yml file that the Action reads:
fail-on-severity: high
allow-dependencies-licenses:
- "pkg:npm/@acme/vendor-sdk"
allow-ghsas:
- "GHSA-7fhm-mqm4-2wp7" # audit: ENG-2104, not reachable from our code
Each entry should have a comment linking to a ticket or investigation note so the next reviewer understands why the exception exists. Review the config quarterly and remove entries that no longer apply, which prevents the allow-list from becoming the place flagged PRs go to die.
How do I combine this with branch protection?
Add the Dependency Review check to your branch protection rules as a required status check. Under Settings → Branches → main → Require status checks to pass before merging, tick the check name that matches your job. Now a PR that introduces a blocked package cannot merge, no matter how much the author wants to bypass.
Combine with CODEOWNERS for security-sensitive files:
# .github/CODEOWNERS
package.json @acme/security
go.mod @acme/security
requirements.txt @acme/security
CODEOWNERS plus Dependency Review gives you two layers: the Action catches policy violations automatically, and the CODEOWNER review catches cases where the author wrote a deny-ghsas override that security would not approve.
How do I surface the output for the whole team?
comment-summary-in-pr: always is the most useful setting. It posts a compact table into the PR conversation every time the Action runs, which means every reviewer on the PR sees the same summary without digging into the Actions tab. The comment looks like:
### Dependency Review
| Package | Version | Severity | License |
|---------|---------|----------|---------|
| minimist | 1.2.6 → 1.2.8 | moderate | MIT |
| lodash | n/a → 4.17.21 | high | MIT |
Add a base-ref and head-ref if you need to compare against something other than the PR base:
with:
base-ref: release-2024.10
head-ref: feature/new-api
This is useful for long-lived release branches where the default branch comparison does not match what you are actually shipping.
How do I run the same check locally before pushing?
GitHub does not ship a local clone of Dependency Review, but you can get close with the open-source deps.dev CLI or with osv-scanner:
brew install osv-scanner # or go install github.com/google/osv-scanner/cmd/osv-scanner@latest
osv-scanner --lockfile=package-lock.json --format=table
This is not identical to what Dependency Review runs, because OSV and GHSA overlap but are not the same, but it catches most issues before the PR is even opened. Add it as a pre-commit hook or a make check target to shorten the feedback loop from minutes to seconds.
How Safeguard Helps
Safeguard extends Dependency Review's PR-time checks with reachability analysis, so a flagged GHSA that your code never calls is demoted automatically while a reachable one is escalated with Griffin AI's suggested fix. SBOMs produced on every push give a continuous view across branches, not just on PR diff. Policy gates enforce license and severity rules at merge and at release, and override decisions made in dependency-review-config.yml are mirrored in Safeguard's own mitigation records so audit teams see one consistent history rather than two disconnected systems.