Dependency Audit Report
Produce a monthly dependency and security audit report across configured repositories using Sourcegraph search and GitHub CLI tools. The report identifies outdated dependencies, known CVE references, and pending dependency update PRs.
Configuration
See _shared/report-config.md for the standard config resolution pattern.
Config schema (~/.claude/skills/dependency-audit/config.json):
repos: list of repository name strings (Sourcegraph/gh CLI format)
Required scope: at least one repos entry.
Arguments
- repos: list of repository names to audit (must match Sourcegraph and gh CLI format)
Workflow
Identify dependency files. For each repo, use list_files to check for:
- Python:
requirements.txt, requirements.in, pyproject.toml, setup.py
- Java/Kotlin:
build.gradle, build.gradle.kts, dependencies.lock, gradle.lockfile
- JavaScript/TypeScript:
package.json, package-lock.json, yarn.lock
- Go:
go.mod, go.sum
- Read the primary dependency files with
read_file to catalog declared dependencies.
Search for known CVE references. For each repo, use keyword_search with query repo:^{repo}$ CVE- to find any explicit CVE references in code, comments, or config. Also search with nls_search for repo:^{repo}$ vulnerability advisory security patch to find security-related mentions.
Search for outdated dependency patterns. Use keyword_search for common staleness signals per ecosystem:
- Python:
repo:^{repo}$ file:requirements pinned versions — look for == pinned versions that may be outdated.
- Java:
repo:^{repo}$ file:build.gradle — check for deprecated dependency declarations.
- JS:
repo:^{repo}$ file:package.json — read and identify major version gaps.
Check dependency update PRs. For each repo, use gh CLI:
gh pr list --repo {repo} --state open --label "dependencies" --json number,title,createdAt,author to find dependabot/renovate PRs.
gh pr list --repo {repo} --state open --search "author:dependabot author:renovate bump update" --json number,title,createdAt,author as a fallback if no label exists.
- Classify: how many are open, how old is the oldest, are any security-critical (title contains "security" or "CVE").
Check for deprecated or removed packages. Use keyword_search to search for known deprecated patterns:
repo:^{repo}$ (deprecated|end-of-life|EOL|no longer maintained) in dependency-adjacent files.
Generate report. Output markdown:
## Dependency Audit — {date}
Repos audited: {N}
### Summary
- Repos with open dependency PRs: {N} | Total open dependency PRs: {N}
- Repos with CVE references: {N} | Security-critical PRs: {N}
- Oldest unmerged dependency PR: {age in days}
### Security Findings
(For each CVE reference found: repo, file, CVE ID, context snippet, severity if known)
### Open Dependency Update PRs
| Repo | PR | Title | Age (days) | Security? |
|---|---|---|---|---|
(All open dependabot/renovate PRs across repos, sorted by age descending)
### Stale Dependency PRs (> 30 days open)
(For each: repo, PR number, title, age, why it might be stuck)
### Dependency Ecosystem Summary
| Repo | Ecosystem | Dependency File | Declared Deps | Pinned | Floating |
|---|---|---|---|---|---|
(Per-repo breakdown of dependency management approach)
### Flags
(Concerning signals: old unmerged security PRs, CVEs in code, no dependency update mechanism)
Deliver as HTML. Follow the shared HTML delivery pattern in _shared/html-delivery.md. Report name: dependency-audit. TLDR includes repos audited, security findings count, and oldest unmerged dependency PR age.
Terminate. Report is complete when all repos are audited and findings compiled.
Design Principles
- Team-level only. Aggregate to team level — it is the right granularity for a periodic digest. Don't attribute dependency debt to individuals.
- Deterministic math first, LLM narrates only. PR counts, ages, and CVE occurrences must be computed from actual API data. The LLM summarizes but never invents severity ratings or vulnerability assessments.
- Pair metrics with counter-metrics. Never report open dependency PRs without showing merge rate. If showing CVE references, also show whether they've been addressed.
Golden Rules
- Security PRs go first. Any dependency PR with "security" or "CVE" in the title gets flagged and surfaced at the top.
- Age is the key metric for dependency PRs. A 3-day-old PR is routine. A 90-day-old PR is a risk. Sort by age, flag anything over 30 days.
- Don't assess vulnerability severity yourself. Report what's found (CVE IDs, PR titles) and let the reader assess. The LLM is not a security scanner.
- Check ALL repos, not a sample. Every configured repo gets a full audit.
- No dependency update mechanism is itself a finding. If a repo has no dependabot/renovate PRs and no recent dependency changes, flag it — dependencies are frozen, not up-to-date.
Anti-Rationalization Counter-Table
| Excuse |
Reality |
| "No CVEs found so dependencies are secure." |
Absence of CVE references in code does not mean absence of vulnerabilities. Report what you found and note the limitation. |
| "I checked the main repo, the others are small." |
Audit ALL configured repos. Small repos with outdated dependencies are still a risk. |
| "There are too many dependency PRs to list." |
List them all in the table. The reader needs the complete picture to prioritize. |
| "I can't determine if dependencies are outdated without a registry lookup." |
You can report: pinned versions, dependency PR age, and absence of update mechanisms. That's actionable without registry lookups. |
| "The repo uses a custom dependency system so I skipped it." |
Report what dependency files exist and note the non-standard setup. Don't silently skip. |
Termination Labels
| Label |
Meaning |
report_complete |
All repos audited, CVE search done, dependency PRs cataloged, flags raised |
report_partial |
Some repos audited but errors prevented full coverage — noted which |
no_repos_configured |
No repos specified — need config.json or user input |
api_error |
Sourcegraph or GitHub API unreachable |
Self-Review Checklist
1---2name: dependency-audit3description: Use when auditing dependencies, checking for outdated packages, reviewing security vulnerabilities, scanning for CVEs, or checking dependabot/renovate PR status. Trigger phrases: dependency audit, security audit, outdated dependencies, CVE check.4---56# Dependency Audit Report78Produce a monthly dependency and security audit report across configured repositories using Sourcegraph search and GitHub CLI tools. The report identifies outdated dependencies, known CVE references, and pending dependency update PRs.910## Configuration1112See [`_shared/report-config.md`](../_shared/report-config.md) for the standard config resolution pattern.1314**Config schema** (`~/.claude/skills/dependency-audit/config.json`):15- `repos`: list of repository name strings (Sourcegraph/gh CLI format)1617**Required scope:** at least one `repos` entry.1819## Arguments2021- **repos**: list of repository names to audit (must match Sourcegraph and gh CLI format)2223## Workflow24251. **Identify dependency files.** For each repo, use `list_files` to check for:26 - Python: `requirements.txt`, `requirements.in`, `pyproject.toml`, `setup.py`27 - Java/Kotlin: `build.gradle`, `build.gradle.kts`, `dependencies.lock`, `gradle.lockfile`28 - JavaScript/TypeScript: `package.json`, `package-lock.json`, `yarn.lock`29 - Go: `go.mod`, `go.sum`30 - Read the primary dependency files with `read_file` to catalog declared dependencies.31322. **Search for known CVE references.** For each repo, use `keyword_search` with query `repo:^{repo}$ CVE-` to find any explicit CVE references in code, comments, or config. Also search with `nls_search` for `repo:^{repo}$ vulnerability advisory security patch` to find security-related mentions.33343. **Search for outdated dependency patterns.** Use `keyword_search` for common staleness signals per ecosystem:35 - Python: `repo:^{repo}$ file:requirements pinned versions` — look for `==` pinned versions that may be outdated.36 - Java: `repo:^{repo}$ file:build.gradle` — check for deprecated dependency declarations.37 - JS: `repo:^{repo}$ file:package.json` — read and identify major version gaps.38394. **Check dependency update PRs.** For each repo, use `gh` CLI:40 - `gh pr list --repo {repo} --state open --label "dependencies" --json number,title,createdAt,author` to find dependabot/renovate PRs.41 - `gh pr list --repo {repo} --state open --search "author:dependabot author:renovate bump update" --json number,title,createdAt,author` as a fallback if no label exists.42 - Classify: how many are open, how old is the oldest, are any security-critical (title contains "security" or "CVE").43445. **Check for deprecated or removed packages.** Use `keyword_search` to search for known deprecated patterns:45 - `repo:^{repo}$ (deprecated|end-of-life|EOL|no longer maintained)` in dependency-adjacent files.46476. **Generate report.** Output markdown:4849```50## Dependency Audit — {date}51Repos audited: {N}5253### Summary54- Repos with open dependency PRs: {N} | Total open dependency PRs: {N}55- Repos with CVE references: {N} | Security-critical PRs: {N}56- Oldest unmerged dependency PR: {age in days}5758### Security Findings59(For each CVE reference found: repo, file, CVE ID, context snippet, severity if known)6061### Open Dependency Update PRs62| Repo | PR | Title | Age (days) | Security? |63|---|---|---|---|---|64(All open dependabot/renovate PRs across repos, sorted by age descending)6566### Stale Dependency PRs (> 30 days open)67(For each: repo, PR number, title, age, why it might be stuck)6869### Dependency Ecosystem Summary70| Repo | Ecosystem | Dependency File | Declared Deps | Pinned | Floating |71|---|---|---|---|---|---|72(Per-repo breakdown of dependency management approach)7374### Flags75(Concerning signals: old unmerged security PRs, CVEs in code, no dependency update mechanism)76```77787. **Deliver as HTML.** Follow the shared HTML delivery pattern in [`_shared/html-delivery.md`](../_shared/html-delivery.md). Report name: `dependency-audit`. TLDR includes repos audited, security findings count, and oldest unmerged dependency PR age.79808. **Terminate.** Report is complete when all repos are audited and findings compiled.8182## Design Principles83841. **Team-level only.** Aggregate to team level — it is the right granularity for a periodic digest. Don't attribute dependency debt to individuals.852. **Deterministic math first, LLM narrates only.** PR counts, ages, and CVE occurrences must be computed from actual API data. The LLM summarizes but never invents severity ratings or vulnerability assessments.863. **Pair metrics with counter-metrics.** Never report open dependency PRs without showing merge rate. If showing CVE references, also show whether they've been addressed.8788## Golden Rules89901. **Security PRs go first.** Any dependency PR with "security" or "CVE" in the title gets flagged and surfaced at the top.912. **Age is the key metric for dependency PRs.** A 3-day-old PR is routine. A 90-day-old PR is a risk. Sort by age, flag anything over 30 days.923. **Don't assess vulnerability severity yourself.** Report what's found (CVE IDs, PR titles) and let the reader assess. The LLM is not a security scanner.934. **Check ALL repos, not a sample.** Every configured repo gets a full audit.945. **No dependency update mechanism is itself a finding.** If a repo has no dependabot/renovate PRs and no recent dependency changes, flag it — dependencies are frozen, not up-to-date.9596## Anti-Rationalization Counter-Table9798| Excuse | Reality |99|---|---|100| "No CVEs found so dependencies are secure." | Absence of CVE references in code does not mean absence of vulnerabilities. Report what you found and note the limitation. |101| "I checked the main repo, the others are small." | Audit ALL configured repos. Small repos with outdated dependencies are still a risk. |102| "There are too many dependency PRs to list." | List them all in the table. The reader needs the complete picture to prioritize. |103| "I can't determine if dependencies are outdated without a registry lookup." | You can report: pinned versions, dependency PR age, and absence of update mechanisms. That's actionable without registry lookups. |104| "The repo uses a custom dependency system so I skipped it." | Report what dependency files exist and note the non-standard setup. Don't silently skip. |105106## Termination Labels107108| Label | Meaning |109|---|---|110| `report_complete` | All repos audited, CVE search done, dependency PRs cataloged, flags raised |111| `report_partial` | Some repos audited but errors prevented full coverage — noted which |112| `no_repos_configured` | No repos specified — need config.json or user input |113| `api_error` | Sourcegraph or GitHub API unreachable |114115## Self-Review Checklist116117- [ ] All configured repos were audited118- [ ] CVE keyword search was run on every repo119- [ ] Dependency update PRs were checked via gh CLI for every repo120- [ ] PR ages computed and stale PRs (>30 days) flagged121- [ ] Security-critical PRs identified and surfaced first122- [ ] Dependency ecosystem summary shows what files exist per repo123- [ ] Flags section surfaces repos with no update mechanism124- [ ] HTML version uploaded to S3 with commuter link (unless `--no-html` or upload failed with noted fallback)125- [ ] Slack/chat delivery uses TLDR + link, not the full report