-
Notifications
You must be signed in to change notification settings - Fork 31
MLE-29893: Add security-vulnerability-triage copilot skill #606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop-11.3
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| --- | ||
| name: security-vulnerability-triage | ||
| description: > | ||
| Analyze, triage, and rescore security vulnerability tickets (CVE, BDSA, | ||
| GHSA, Dependabot, security advisory). Use when the user mentions a CVE/BDSA | ||
| ID, asks whether the product is impacted by an advisory, asks to rescore a | ||
| vulnerability ticket, or needs a Jira analysis comment for a security | ||
| finding. Specialized for Java/Maven projects (e.g. MarkLogic ContentPump / | ||
| MLCP) with transitive dependency tracing and bytecode reachability analysis. | ||
| --- | ||
|
|
||
| # Security Vulnerability Analysis | ||
|
|
||
| A repeatable, human-in-the-loop process for triaging and rescoring security | ||
| vulnerability tickets. | ||
|
|
||
| ## How to invoke | ||
|
|
||
| **All you need:** a Jira bug ID (format `MLE-*****`) that references a CVE, BDSA, or GitHub Dependabot alert. | ||
|
|
||
| - **CVE ticket:** Just the Jira bug ID (e.g. `MLE-29365`). The skill will ask before fetching the advisory from NVD. | ||
| - **BDSA ticket:** Paste the BDSA text along with the Jira bug ID (BDSAs are private and can't be fetched). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is incorrect, we can setup the connection between copilot and BD simply by providing the api token. This skill should ask for the BD api token and make sure to not persist it anywhere |
||
| - **Dependabot / GHSA ticket:** Just the Jira bug ID. The skill will fetch the GHSA advisory from GitHub if you confirm, or you can paste it. | ||
| - **Multiple tickets:** List the Jira bug IDs (e.g. `MLE-29365, MLE-29366, ...`). The skill processes each one through the full 9-step flow and produces a summary table at the end (`bug ID | verdict | score | status`). Confirmed-impact tickets are flagged prominently in the summary. | ||
|
|
||
| The skill always pauses at two points: when advisory text is missing, and before posting the draft Jira comment. | ||
|
|
||
| ## Ground rules (must always hold) | ||
|
|
||
| 1. **Never infer the vulnerable component from a CVE ID, score, or web-search summary.** Read the actual advisory text (Black Duck, NVD, GHSA) before making any claim. | ||
| 2. **Never assume the CVE↔BDSA mapping.** Confirm from the advisory itself. | ||
| 3. **Never use "language binding" as an exclusion unless the advisory explicitly names the affected binding** (e.g. "Node.js only", "Swift only"). Otherwise treat as cross-language. | ||
| 4. **"On the classpath" ≠ "used at runtime".** Confirm reachability with source search *and* bytecode inspection (`javap -c`). | ||
| 5. **Never post a Jira analysis comment without explicit user approval.** | ||
| 6. **Always verify Jira field updates with a follow-up GET.** The API returns 200 OK even when custom fields silently fail to save (Agile Team, cascading selects, Fix Version by name, Sprint as object). Confirm fields actually persisted before transitioning status. | ||
| 7. **Only run on security vulnerability tickets.** Verify in step 1 that the ticket is actually a CVE / BDSA / GHSA / Dependabot bug (via component, labels, title prefix, or advisory ID in the description). If it isn't, stop and tell the user — don't try to fit a non-security ticket through this workflow. | ||
|
|
||
| ## The 9-step process | ||
|
|
||
| Follow these steps in order. Do not skip steps. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which step recalculates the cvss score? |
||
|
|
||
| ### 1. Gather the ticket | ||
| Fetch the ticket with `mcp-atlassian-jira_get_issue` and **verify it's a security vulnerability ticket** before doing anything else. Signals to look for: | ||
| - Component is `Security`, or label includes `Security` / `CVE` / `BDSA` | ||
| - Title contains `[CVE]`, `[BDSA]`, `[GHSA]`, or a CVE/BDSA/GHSA ID | ||
| - Description references a CVE / BDSA / GHSA ID or a Dependabot alert | ||
| - A CVSS score field is set | ||
|
|
||
| If **none** of these match, stop and tell the user the ticket doesn't look like a security vulnerability and the skill won't proceed. Do not guess. | ||
|
|
||
| If valid, capture: BDSA/CVE/GHSA ID, current CVSS score and severity, affected library + version, project key, component. | ||
|
|
||
| ### 2. Get the advisory text | ||
| Ask the user to paste the Black Duck advisory, or fetch from NVD (`https://nvd.nist.gov/vuln/detail/<CVE-ID>`). **Do not** infer the vulnerable component from the CVE ID alone or from search engine summaries. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the user connect to blackduck using token and copilot get the advisory from blackduck? |
||
|
|
||
| ### 3. Identify the vulnerable component | ||
| From the advisory text, pinpoint exactly what is affected: | ||
| - Specific class or file (e.g. `TSSLTransportFactory.java`) | ||
| - Language binding (e.g. `c_glib`, Rust impl, Node.js only) | ||
| - Specific code path or feature (e.g. "only when SSL is enabled") | ||
|
|
||
| ### 4. Trace the dependency chain | ||
| Find how the vulnerable library enters the product's classpath. | ||
| - Check **explicit** deps in `pom.xml` (root and module poms). | ||
| - Check **transitive** sources by inspecting direct dependency POMs in the Maven cache (`~/.m2/repository/...`). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does user need to keep cache clean before running this workflow? Or can user specify a different Maven cache folder? |
||
| - Run `mvn dependency:tree -Dincludes=<groupId>:<artifactId> -Dverbose` to enumerate every path. | ||
| - Verify against the **current version** of each candidate — a dep may have been added years ago for a use case that no longer applies. | ||
|
|
||
| **Red flag:** an explicit dependency with no obvious current consumer. | ||
|
|
||
| ### 5. Analyze reachability | ||
| - Source search (`grep`/`glob`) for imports and references. | ||
| - For Java: confirm whether the vulnerable class is loaded eagerly (static initializer / class referenced at startup) or lazily (only on specific method invocation). Use `javap -v -c -p -classpath <jar> <FQCN>` and inspect the `static {}` block plus the constant pool. | ||
| - If the vulnerable code path is **unreachable**, removing the library silently eliminates it; if eagerly loaded, removal would cause startup failures (signal it's actually used). | ||
|
|
||
| ### 6. Draft the analysis comment | ||
| Use the Jira comment template below. **Always** show the draft to the user for review before posting. | ||
|
|
||
| ### 7. Review with user | ||
| Wait for explicit approval. Never post without it. | ||
|
|
||
| ### 8. Post the comment | ||
| Use `mcp-atlassian-jira_add_comment` with the approved body. | ||
|
|
||
| ### 9. Update the ticket | ||
| - **Title:** append ` - Rescore <N>` (e.g. ` - Rescore 0`). | ||
| - **Calculated CVSS field (`customfield_11168`):** update to the rescored value. | ||
| - **Priority:** adjust to match rescored severity. | ||
| - **Status:** transition to **In Review** (use `mcp-atlassian-jira_get_transitions` then `mcp-atlassian-jira_transition_issue`). | ||
|
|
||
| ## Rescoring guidance | ||
|
|
||
| | Verdict | Score | When | | ||
| |---|---|---| | ||
| | Not impacted | 0 | Vulnerable component/code path unreachable, or affected binding not used. | | ||
| | Reduced | < advisory | Reachable but mitigated (e.g. only in disabled feature, requires authenticated admin). | | ||
| | Confirmed | = advisory | Reachable in default config / typical use. | | ||
|
|
||
| State the **basis** for the score in the comment, not just the number. | ||
|
|
||
| ## Jira analysis comment template | ||
|
|
||
| ```markdown | ||
| **Root Cause — How [library] enters [product]'s classpath** | ||
|
|
||
| [Explain how the vulnerable library ends up on the classpath — direct dep, | ||
| transitive dep, or both. Name the specific dependency chain.] | ||
|
|
||
| --- | ||
|
|
||
| **Impact Analysis** | ||
|
|
||
| [Name the CVE/BDSA and the specific vulnerable component (class, file, or | ||
| binding) it affects.] | ||
|
|
||
| [Lead with what the product does — which code/files use the library and | ||
| what operations they perform. Then state whether the vulnerable | ||
| component/code path is reachable from the product's usage. If not impacted, | ||
| explain why. If impacted, describe the attack surface and preconditions.] | ||
|
|
||
| --- | ||
|
|
||
| **Suggested Fix** | ||
|
|
||
| [Concrete change — upgrade to fixed version, remove dep, add exclusion, | ||
| apply workaround, or "no action required — code path unreachable".] | ||
|
|
||
| --- | ||
|
|
||
| **Rescore Justification — <score> (<verdict>)** | ||
|
|
||
| [Final conclusion: whether the vulnerable component is reachable, what the | ||
| real-world risk is, and the basis for the score assigned.] | ||
| ``` | ||
|
|
||
| ### Comment style notes | ||
|
|
||
| - Lead each section with the **conclusion**, then the evidence. | ||
| - Cite specific class names, file paths, and method names — not generalities. | ||
| - Quote relevant POM snippets and `javap` output when they materially support the conclusion. | ||
| - Avoid excessive bold formatting; plain prose reads better in Jira. | ||
|
|
||
| ## Lessons learned (case studies) | ||
|
|
||
| ### The libthrift transitive trap | ||
| During the Apache Thrift BDSA batch (MLE-29365–29372), libthrift was first attributed to Hadoop YARN, but Hadoop 3.x had dropped Thrift entirely. The actual transitive source was Apache Jena 4.9.0 (`jena-arq`), used only for RDF/Thrift serialization — a path MLCP never invokes. Stopping at the first plausible attribution would have produced a fix recommendation that did nothing. Always verify against the **current** POM of every candidate, not its history. | ||
|
|
||
| ### BDSA score doesn't mean BDSA scope | ||
| CVE-2026-41636, CVE-2026-41604, and BDSA-2026-9090 all carried 7.9 High CVSS scores against Apache Thrift. The advisory text revealed they affected Node.js and Swift bindings only — Java was unaffected. Without reading the actual advisory, every row would have looked like a critical Java vulnerability. | ||
|
|
||
| ### Eager vs lazy class loading | ||
| Source-grep proved Jena imports libthrift, but that didn't prove the code was reachable. Running `javap -c -p` showed libthrift classes were only referenced inside method bodies, never in a `static {}` block — so removing libthrift would not cause a JVM startup failure. Source search proves intent; bytecode proves behavior. | ||
|
|
||
| ### Jira API silently accepts wrong field formats | ||
| On step 9 updates, several silent failures occurred: Agile Team set as `[{"name": "MLE-Light"}]` (wrong; needs `["MLE-Light"]`), cascading Product-Module missing child value, Fix Version set by name instead of ID. Jira returned 200 OK each time but the fields stayed blank. Always GET-after-PUT before transitioning status. | ||
|
|
||
| ### BDSA may bundle multiple CVE years | ||
| BDSA-2026-8506 mapped to CVE-2025-48431 — a 2025 CVE inside a 2026 BDSA. The BDSA year reflects when Black Duck issued the advisory, not when the CVE was published. The BDSA ↔ CVE mapping must come from the advisory text, not from pattern-matching IDs. | ||
|
|
||
| ### Never post a comment without explicit review | ||
| On one ticket in the Thrift batch, an incorrect Product-Module value was written before user review and then had to be corrected across all 8 tickets. The cost of a quick review is seconds; the cost of a Jira correction across N tickets compounds. Always show the draft to the user first. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think instead of keep repeating jira bug id in this section, probably ask the user to provide a jira id at first, check whether necessary info is listed in the jira ticket, if not, stop and ask the user.