Skip to content

Commit 382989e

Browse files
committed
LCORE-2118: Add Claude Code skill for Dependabot CVE triage
1 parent 8344b51 commit 382989e

1 file changed

Lines changed: 95 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
name: file-dependabot-cves
3+
description: Fetch Dependabot alerts, cross-reference against LCORE Jira tickets, and file tickets for gaps
4+
---
5+
6+
Audit Dependabot vulnerabilities for `$repo` (default: `lightspeed-core/lightspeed-stack`) and cross-reference them against existing LCORE Jira tickets.
7+
8+
## Step 1: Fetch Dependabot alerts
9+
10+
Fetch open Dependabot alerts using:
11+
12+
```
13+
gh api "repos/$repo/dependabot/alerts" --paginate --jq '.[] | select(.state == "open") | {number, state, severity: .security_vulnerability.severity, package: .security_vulnerability.package.name, ecosystem: .security_vulnerability.package.ecosystem, summary: .security_advisory.summary, cve: (.security_advisory.cve_id // "N/A"), ghsa: .security_advisory.ghsa_id, created: .created_at, fixed_version: (.security_vulnerability.first_patched_version.identifier // "N/A")}'
14+
```
15+
16+
If `$repo` is not provided, default to `lightspeed-core/lightspeed-stack`. Deduplicate results by (CVE + package name) when a CVE is present, or (GHSA ID + package name) when CVE is null/N/A. This prevents collapsing distinct GHSA-only advisories for the same package into a single entry.
17+
18+
## Step 2: Present severity summary
19+
20+
Present a summary table with counts by severity (Critical, High, Medium, Low), then a breakdown table grouped by package: Package | Severity | CVE | Summary | Fix Version.
21+
22+
## Step 3: Search LCORE Jira for existing coverage
23+
24+
!Requires JIRA Atlassian MCP
25+
26+
Search LCORE Jira for existing tickets per affected package. Batch package names into OR clauses to minimize API calls:
27+
28+
- By summary: `project = LCORE AND (summary ~ "pkg1" OR summary ~ "pkg2" ...)`
29+
- By CVE label: `project = LCORE AND labels in ("CVE-XXXX-XXXXX", ...)`
30+
31+
Fields: `summary,status,assignee,priority,labels`. Limit: 50. Paginate if needed.
32+
33+
## Step 4: Cross-reference and classify
34+
35+
Cross-reference each Dependabot alert to its LCORE ticket(s) and classify as:
36+
- **Covered**: open/in-progress ticket exists
37+
- **Closed**: ticket done
38+
- **Missing**: no ticket
39+
40+
Present:
41+
1. A coverage table: Vulnerability | Sev. | Dependabot # | LCORE Ticket(s) | Status | Assignee
42+
2. A **gaps table** listing only the missing vulnerabilities with their GitHub alert title (from `security_advisory.summary`), severity, CVE, and fix version
43+
3. Key findings: coverage ratio, unassigned high/critical items, duplicate tickets that could be consolidated
44+
45+
## Step 5: Verify gaps
46+
47+
For each gap, cross-reference in JIRA (full-text search by CVE ID) and GitHub (confirm alert is still open) to verify it is a real missing issue. Drop false positives (e.g., already-closed tickets, stale alerts).
48+
49+
## Step 6: Ask user which gaps to file
50+
51+
Ask the user:
52+
- Whether they want to create LCORE tickets for the missing vulnerabilities
53+
- Which severity levels to include (e.g. "only medium and above", "all", or specific ones)
54+
- The target fix version (look up available versions from `jira_get_project_versions` for LCORE)
55+
- The component to assign (look up available components from `jira_get_project_components` for LCORE)
56+
57+
## Step 7: Fetch full advisory details and draft tickets
58+
59+
For each vulnerability the user wants to file, fetch the full Dependabot advisory description:
60+
61+
```
62+
gh api "repos/$repo/dependabot/alerts/$alert_number" --jq '{summary: .security_advisory.summary, description: .security_advisory.description, cve: (.security_advisory.cve_id // "N/A"), remediation: (.security_vulnerability.first_patched_version.identifier // "No fix available"), vulnerable_range: .security_vulnerability.vulnerable_version_range}'
63+
```
64+
65+
Structure each ticket as:
66+
67+
| Field | Value |
68+
|-------|-------|
69+
| **Project** | LCORE |
70+
| **Type** | Vulnerability |
71+
| **Title** | The original GitHub advisory summary (from `security_advisory.summary`) |
72+
| **Component** | As chosen by user |
73+
| **Fix Version** | As chosen by user |
74+
| **Labels** | The CVE ID (if available), Security |
75+
| **Description** | The full `security_advisory.description` from Dependabot, followed by `**Remediation:** Upgrade <package> to >= <fix_version>` (or "No upstream fix available yet" if no fix exists, including the vulnerable range). |
76+
77+
Present all drafted tickets in a table to the user for review before creating them.
78+
79+
## Step 8: Find the parent CVE epic
80+
81+
Search for the parent epic: `project = LCORE AND issuetype = Epic AND summary ~ "CVE" AND summary ~ "lightspeed-stack" ORDER BY created DESC`. Pick the one whose fix version matches the user's chosen fix version. If ambiguous or none found, ask the user.
82+
83+
## Step 9: Create tickets after user confirmation
84+
85+
Only after the user explicitly confirms the drafts, create the tickets using `jira_create_issue` with:
86+
- `project_key`: LCORE
87+
- `issue_type`: Vulnerability
88+
- `summary`: the GitHub advisory title
89+
- `description`: as structured above
90+
- `components`: user's chosen component
91+
- `additional_fields`: `{"fixVersions": [{"id": "<version_id>"}], "labels": ["<CVE-ID>", "Security"], "parent": "<EPIC_KEY>"}`
92+
93+
Omit `parent` only if the user chose to skip it.
94+
95+
Report back the created ticket keys and links.

0 commit comments

Comments
 (0)