Dependabot Alerts, Security Updates, Version Updates, Dependency Review, and Policy: Guided Hands-On Workflow and Core Operations
This lesson turns the mental model into a reproducible public-repository lab. You will establish a small lockfile, commit a bounded Dependabot policy, enable alert/security-update features explicitly, run dependency review on a real pull-request delta, and keep vulnerability simulation separate from live vulnerable code.
Learning objectives
- Create and verify a free-compatible npm dependency repository without running package scripts.
- Configure bounded weekly Dependabot version updates and enable alerts/security updates separately.
- Pin a dependency-review workflow to immutable action commits with least-privilege permissions.
- Generate or simulate an update PR and inspect author, exact head SHA, checks, and alert state.
dependabot.yml. Exact
shell snippets use Bash/Git Bash; Windows learners can run them in Git
Bash, while the GitHub UI/API state is shell-independent. Dependency
review is available for public repositories. The sample uses npm
because its manifest/lock format is easy to inspect; the control model
transfers to other supported ecosystems.
is-number@6.0.0, an old but not intentionally vulnerable
dependency, and installs lock metadata only with
--ignore-scripts. Do not seed a known vulnerable package
merely to manufacture an alert. If no real alert exists, use the
synthetic alert fixture in this lesson.
1. Preflight: predict the hosted state before changing it
Write down these predictions: (1) committing
.github/dependabot.yml will schedule version checks but
will not itself enable vulnerability alerts; (2) enabling
alerts/security updates changes repository security settings but
does not modify Git history; (3) the dependency-review workflow will
run on PRs with only contents: read; and (4) the sample
package update should produce dependency-change evidence but no
deliberately engineered vulnerability.
gh auth status --hostname github.com
OWNER=$(gh api -H "X-GitHub-Api-Version: 2026-03-10" user --jq .login)
REPO="$OWNER/dependabot-policy-lab"
gh repo create "$REPO" --public --add-readme --clone
cd dependabot-policy-lab
git branch --show-current
gh repo view "$REPO" --json nameWithOwner,visibility,viewerPermission,defaultBranchRef
2. Create a deterministic tiny dependency state
The lab never executes the dependency. It asks npm to create a lock file while lifecycle scripts are disabled.
cat > package.json <<'JSON'
{
"name": "dependabot-policy-lab",
"private": true,
"version": "1.0.0",
"dependencies": {
"is-number": "6.0.0"
}
}
JSON
npm install --package-lock-only --ignore-scripts
node -e 'const p=require("./package-lock.json"); console.log(p.packages["node_modules/is-number"].version)'
Expected local observation: the lock file records
6.0.0. The lock file is the concrete dependency state
the graph and dependency-review delta can reason about.
3. Add a bounded version-update policy
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 2
labels:
- "dependencies"
groups:
routine:
applies-to: version-updates
patterns:
- "*"
mkdir -p .github/workflows
cat > .github/dependabot.yml <<'YAML'
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 2
labels:
- "dependencies"
groups:
routine:
applies-to: version-updates
patterns:
- "*"
YAML
open-pull-requests-limit bounds review concurrency. The
group provides a stable place to evolve grouping policy. With one
dependency it is intentionally boring; production repositories often
need patterns/exclusions rather than “group everything.”
4. Add dependency review as a PR admission signal
The workflow pins both GitHub-owned actions to full commit SHAs resolved at chapter generation time. A full SHA avoids silently changing executable action code while a PR is under review; update automation can propose SHA updates later.
name: Dependency review
on:
pull_request:
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: Checkout reviewed revision
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 line, verified 2026-08-19
with:
persist-credentials: false
- name: Review dependency delta
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
with:
fail-on-severity: high
cat > .github/workflows/dependency-review.yml <<'YAML'
name: Dependency review
on:
pull_request:
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: Checkout reviewed revision
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 line, verified 2026-08-19
with:
persist-credentials: false
- name: Review dependency delta
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
with:
fail-on-severity: high
YAML
git add package.json package-lock.json .github
git commit -m "Add dependency policy lab"
git push
BASE_SHA=$(git rev-parse HEAD)
printf 'baseline=%s\n' "$BASE_SHA"
This workflow needs read access to repository contents and dependency-review data; it does not need Issues, Packages, deployments, secrets, or a write token.
5. Enable/inspect alerts and security updates without hiding the state transition
In the current repository settings, open Security → Advanced Security. Confirm the dependency graph is active. Enable Dependabot alerts, then enable Dependabot security updates. These are repository security settings, so repository administrators/owners are the relevant role. Do not change organization-wide defaults for this disposable lab.
Afterward, inspect the dependency graph and the Dependabot page. Version-update status is also visible from the dependency graph/Dependabot surface after the configuration is processed.
# Read-only: version-update PRs, if Dependabot has created any.
gh pr list --repo "$REPO" --author app/dependabot --state all \
--json number,title,state,headRefName,baseRefName,updatedAt
# Read-only alert inventory. Empty [] is a valid result for this safe lab.
gh api --paginate \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
"repos/$REPO/dependabot/alerts?state=open&per_page=100" \
--jq '.[] | {number,state,package:.dependency.package.name,severity:.security_advisory.severity,manifest:.dependency.manifest_path}'
If the API returns 403/404, distinguish
feature state and alert-view permission from “there are no alerts.”
An empty successful response is different from an
authorization/feature failure.
6. If there is no real alert, use a synthetic alert fixture
The lab package is deliberately not chosen for a known vulnerability. Use this fixture to practice triage vocabulary without introducing exploitable code.
{
"number": 42,
"state": "open",
"dependency": {
"package": {"ecosystem": "npm", "name": "example-vulnerable-lib"},
"manifest_path": "package-lock.json",
"scope": "runtime",
"relationship": "direct"
},
"security_advisory": {
"ghsa_id": "GHSA-FAKE-0000-0000",
"severity": "high",
"summary": "Synthetic training advisory"
},
"security_vulnerability": {
"vulnerable_version_range": "< 2.0.0",
"first_patched_version": {"identifier": "2.0.0"}
}
}
Practice the questions: Is it runtime? Direct? Is a patched version available? What tests cover the changed API? Who owns the remediation? If an exception is proposed, what evidence and expiry date will be recorded? Never dismiss a real alert merely to make a dashboard green.
7. Generate or simulate one update pull request
Dependabot may open a 6.0.0→7.0.0 PR on its own. If it does, use that PR. If scheduling has not produced a PR yet, simulate the same repository delta from a normal branch so dependency review and review policy remain testable.
BOT_PR=$(gh pr list --repo "$REPO" --author app/dependabot --state open --json number --jq '.[0].number // empty')
if [ -n "$BOT_PR" ]; then
echo "Use Dependabot PR #$BOT_PR"
else
git switch -c lab/dependency-update
npm install is-number@7.0.0 --package-lock-only --ignore-scripts
git add package.json package-lock.json
git commit -m "Simulate dependency update to is-number 7.0.0"
git push -u origin HEAD
gh pr create --repo "$REPO" --base "$(gh repo view "$REPO" --json defaultBranchRef --jq .defaultBranchRef.name)" \
--head "lab/dependency-update" \
--title "Lab: dependency update is-number 6 to 7" \
--body "Synthetic update PR used to exercise dependency-review policy; not created by Dependabot."
fi
Record who created the PR. A human simulation proves the dependency delta and review gate, but it does not prove Dependabot actor/secrets behavior. That distinction belongs in the evidence.
8. Observe the PR, check, and exact source state
PR=$(gh pr list --repo "$REPO" --state open --json number --jq '.[0].number')
gh pr view "$PR" --repo "$REPO" --json number,title,author,baseRefName,headRefName,headRefOid,mergeStateStatus,statusCheckRollup
gh pr checks "$PR" --repo "$REPO"
Expected evidence: the head SHA identifies the proposed dependency state, dependency review reports the delta, and ordinary merge status remains separate. If the dependency review check is made required through branch/ruleset governance, merge policy can require it; the action itself does not modify branch protection.
9. Design challenge: choose the control surface
Choose one answer for each scenario and justify it before opening the reveal below: (A) “never accept major updates to a legacy library automatically”; (B) “group patch/minor PRs for five related libraries”; (C) “block a PR that introduces a high-severity dependency”; (D) “Dependabot needs a credential for an external private npm registry.”
| Scenario | Correct surface |
|---|---|
| A |
dependabot.yml ignore/allow
or explicit policy; do not rely on human memory.
|
| B |
groups with narrow patterns/update types.
|
| C | Dependency-review action + required check/ruleset where desired. |
| D | Dependabot private-registry config referencing a Dependabot secret, not an Actions secret. |
Knowledge check
Why does the lab enable alerts in Settings even though
dependabot.yml is committed?
Because alerts/security updates and version updates are separate feature states. The config file schedules/configures version updates; alerts must be enabled separately.
Why is --ignore-scripts used while producing the
lock file?
The lab only needs dependency metadata. Avoiding lifecycle scripts reduces unnecessary execution of package-controlled code during setup.
What does a successful dependency-review check prove?
That the PR dependency delta satisfied the configured dependency-review policy for that run and revision; it does not prove application compatibility or general safety.
Why must you record whether the PR author is Dependabot or your lab account?
Dependabot-triggered workflows have special token/secrets restrictions. A human-created simulation cannot prove those identity restrictions.
The alert API returns 403. Is the correct conclusion “no vulnerabilities”?
No. Preserve the error and inspect feature enablement and permissions. Only a successful empty result supports “no returned open alerts.”
Summary
You now have four independent pieces of evidence: committed dependency state, update configuration, repository vulnerability-feature state, and pull-request dependency review. Keeping them separate makes failures diagnosable and prevents a bot-created PR from bypassing normal review discipline.
Next you will choose update frequency/grouping, security-only versus regular version updates, auto-merge boundaries, ignore/allow policy, and private-registry credential handling based on risk rather than convenience.
Official references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.