|
| 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