Skip to content

✨ feat(libraryscan): migrate to McpScanResult dedicated data model#12

Merged
marcwieserdev merged 10 commits intomainfrom
marc.wieser/update_library_scan_model
Mar 24, 2026
Merged

✨ feat(libraryscan): migrate to McpScanResult dedicated data model#12
marcwieserdev merged 10 commits intomainfrom
marc.wieser/update_library_scan_model

Conversation

@marcwieserdev
Copy link
Copy Markdown
Collaborator

@marcwieserdev marcwieserdev commented Mar 18, 2026

🚀 Motivation

The library scan tool was forwarding the raw pipeline JSON response directly to agents. This response format is costly to parse and makes it hard for agents to correlate objects — for example, vulnerability hashes were stored in metadata maps rather than being embedded in the vulnerability objects they describe. A dedicated, library-centric data model is needed to make vulnerability metadata directly accessible to AI agents.

📚 Documentation

Document Link or Detail
RFC N/A
Incident N/A
Jira Ticket K9VULN-12506

📝 Summary

Migrated the library scan parser and types from the old enricher-based pipeline response (VULNERABILITY_DETECTION / SCORE_ENRICHER / REMEDIATION_ENRICHER keys) to the new McpScanResult schema (version 1), which is library-centric with a deduplicated vulnerability definitions map.

Key changes:

  • VulnerabilityFinding — replaced CVEAliases []string with CVE string; removed free-form Remediation text; added CWEs, CVSSVector, EPSSScore, EPSSPercentile, ExploitSources, ExploitURLs, CISAAdded, DatadogScore, Reachability, Ecosystem, LicenseID, LatestVersion, EolDate, RootParent, FixType, HasRemediation; changed ExploitAvailable from bool to *bool to correctly represent nullable API values
  • parseResponse — iterates the libraries map and enriches each finding from the deduplicated vulnerabilities map, extracting closest/latest fix versions from structured remediation entries
  • Schema version guard — if the response version field is higher than the supported version (1), structured parsing is skipped entirely and the raw JSON is returned so agents can still inspect the payload
  • Formatters (MCP + CLI) — both updated to render all new fields: CVE, CVSS vector, EPSS score/percentile, exploit sources and URLs, CISA KEV date, license, latest available version, root dependency PURL, and reachability

🧪 Testing

  • New tests were added for new logic.
  • Existing tests were updated for new logic, and not only so that they pass!
  • Benchmark results prove that performance is the same or better.

🚧 Staging validation

  • Deployed and monitored using Datadog dashboards.
  • Proof that it works as expected, including profiling or UX screenshots.

🆘 Recovery

Notes for on-call - select only one:

  • The change can be rolled back.
  • Do not roll back. Why?:

marcwieserdev and others added 6 commits March 18, 2026 13:45
… model

Update library scan to consume the new MCP-optimized API response format
(version 1) which uses a library-centric structure with a deduplicated
vulnerabilities map, replacing the old VULNERABILITY_DETECTION enricher format.

- VulnerabilityFinding: replace CVEAliases with CVE, add CWEs, DatadogScore,
  Reachability, Ecosystem, Relation, FixType, HasRemediation, ExploitPoC;
  change ExploitAvailable from bool to *bool to handle null API values
- parser.go: new mcpScanResult struct types; parseResponse now iterates
  libraries map and enriches each finding from the vulnerabilities map
- formatLibraryScanResult (MCP + CLI): display new fields (CVE, Ecosystem,
  Relation, DatadogScore, Reachability, CWEs, ExploitPoC)
- Tests updated throughout for new format and struct fields

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…nown versions

Per the McpScanResult versioning contract: if the response version is higher
than the supported version (1), structured parsing must be rejected to avoid
misreading unknown fields. Instead, return the raw JSON so agents can still
inspect the payload directly.

- parser.go: check version before parsing; set ScanResult.UnsupportedVersion
  and skip structured parsing when version > supportedVersion
- types.go: add UnsupportedVersion field to ScanResult
- formatting.go: when UnsupportedVersion is set, show a warning and render
  the raw JSON response for agents to read
- Tests added for both the parser and formatter degradation paths

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…metadata

Previously only a subset of the McpScanResult schema was decoded. Both the
vulnerability definition and library result contain additional fields that
were silently dropped.

Vulnerability definition — added fields:
  cvssVector, epssScore, epssPercentile, exploitSources, exploitUrls, cisaAdded

Library result — added fields:
  licenseId, latestVersion, eolDate, rootParent

All new fields are propagated through VulnerabilityFinding and rendered in
the MCP formatter: CVSS vector, EPSS score/percentile, exploit sources,
CISA KEV date, license, latest available version, and root dependency PURL.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The CLI formatter (scan.go) was not updated alongside the MCP formatter
when the full vulnerability and library metadata fields were added. Added
the missing fields: licenseId, latestVersion, rootParent, cvssVector,
epssScore/percentile, cwes, exploitSources, exploitPoC, and cisaAdded.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
When exploit URLs are present, list them beneath the exploit warning
line in both the MCP and CLI formatters.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…supported

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@marcwieserdev
Copy link
Copy Markdown
Collaborator Author

marcwieserdev commented Mar 18, 2026

@codex review

(Seems like we still don't have access here :sadcat:)

marcwieserdev and others added 2 commits March 18, 2026 14:25
- Drop RawResponse from successful parse results; only store it for the
  unsupported-version fallback path where agents actually need to read it
- Remove redundant ID field from mcpVulnerabilityDef (GHSAID already set
  from vulnRef.AdvisoryID)
- Simplify EPSS formatting in CLI to avoid mixed Printf/Println pattern

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The id field was dropped from mcpVulnerabilityDef but remained in the
test JSON bodies where it was silently ignored by the decoder.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
marcwieserdev and others added 2 commits March 20, 2026 11:14
…output

- Add Risks field to LibraryInfo, parsed from API response
- Display risks in MCP table column and per-library section header
- Display risks in CLI library header line
- Add Root Parent column to libraries table in MCP output
- Fix vulnerability pluralisation (vulnerabilitys → vulnerabilities)
- Remove next steps sections from all formatters (scan, SBOM, library)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@marcwieserdev marcwieserdev merged commit 48faddf into main Mar 24, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants