Skip to content

Add CVE product status surface for never-shipped packages - #93

Open
atomicturtle wants to merge 3 commits into
resf:mainfrom
atomicturtle:fix/73-cve-status-api
Open

atomicturtle wants to merge 3 commits into
resf:mainfrom
atomicturtle:fix/73-cve-status-api

Conversation

@atomicturtle

Copy link
Copy Markdown
Contributor

Summary

  • Follow-up to #73 / #91. Empty-package RLSAs stay rejected; CVEs Rocky does not ship get an explicit status instead of disappearing from the Rocky API.
  • Classifier materializes fixed / not_shipped / under_investigation per supported product. GET /api/v3/cves and GET /api/v3/vex expose that. Updateinfo is unchanged (package-bearing RLSAs only).
  • OpenVEX maps not_shippednot_affected so scanners are not told the CVE is fixed.

Does not include the EVR≥ matcher from #91.

Test plan

  • bazel test //apollo/tests:test_cve_status
  • Apply apollo/migrations/20260826180000_add_cve_product_statuses.sql and run classify
  • GET /api/v3/cves/{CVE} returns per-product statuses
  • GET /api/v3/vex/cves/{CVE} has no package fix list for not_shipped / under_investigation
  • GET /api/v3/updateinfo/... is unchanged (no status-only RLSAs)

@rockythorn rockythorn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Conditional approve (pending #91, two non-blocking notes)

Tests pass, no merge conflicts with main (including recently merged #88 and #97). This is a well-scoped feature that fills the CVE visibility gap without touching updateinfo or creating empty-package RLSAs.

Architecture: solid

The three-status model (fixed / not_shipped / under_investigation) with the 14-day rematch window is well-reasoned. The priority system (fixed > under_investigation > not_shipped, never downgrade fixed) prevents status thrashing.

New DB table follows the migration convention (apollo/migrations/, -- migrate:up/down, CHECK constraint, indexes). Schema.sql updated to match.

API surface is clean:

  • /api/v3/cves/ and /api/v3/cves/{cve_id} — straightforward status queries
  • /api/v3/vex/cves/{cve_id} — OpenVEX document with correct not_shipped → not_affected mapping
  • /api/v3/vex/products/{product_name} — product-scoped VEX summary
  • Updateinfo intentionally excluded (comment-only change) — correct, scanners shouldn't see status-only entries as package fixes

Workflow plumbing is complete:

  • CveStatusIndexWorkflow in cveindexer for standalone classification
  • RhRematchWorkflow chains: clear blocks → rematch → classify
  • clear_rh_blocks_for_product properly decorated with @activity.defn
  • Both workers (rpmworker, cveindexer) register the activities

Verified

  • bazel test //apollo/tests:test_cve_status passes
  • Migration SQL matches ORM model and schema.sql
  • No merge conflicts with main (post #88 + #97 merges)
  • Status priority constants are tested
  • VEX mapping tested (not_shipped → not_affected, not "affected")
  • Updateinfo exclusion tested (no /cves route on updateinfo router)

Non-blocking notes

1. Upsert loop performance (lines 210-233): The classifier does individual SELECT + UPDATE/INSERT for each CVE inside a transaction. With ~12k CVEs per product (mentioned in the PR description), this is ~24k queries per product. Works but could be 100x faster with a bulk INSERT ... ON CONFLICT via raw SQL. Fine for a background Temporal activity that runs infrequently — flag it as a follow-up if classification takes too long in practice.

2. shipped_package_names_for_product accesses _package_name directly (line 75): It then manually replicates _clean_package_name's module prefix stripping (lines 79-81). If the cleaning logic changes in AdvisoryPackage, this code would drift. Consider calling AdvisoryPackage._clean_package_name() instead of inlining the logic.

Dependency on #91

The PR description states "Does not include the EVR≥ matcher from #91" — the classifier itself doesn't need #91, but the RhRematchWorkflow is designed to be run after the EVR matcher lands. The classification logic and API surface can merge independently, but the rematch workflow is most useful once #91 is in.

Once #91's Python 3.9 compat fix lands, both can merge (in either order for the code, but run rematch after #91 in prod).

Materialize fixed/not_shipped/under_investigation via classifier, API, and
OpenVEX export so resf#73 gaps are visible without empty updateinfo RLSAs.
Include the new activities and routes in library srcs, run
test_cve_status in CI, and map not_shipped to OpenVEX not_affected
so scanners are not told the CVE is fixed.

Signed-off-by: Scott R. Shinn <scott@atomicorp.com>
Avoid drifting module. prefix stripping; note bulk upsert as a follow-up if classify gets slow.
@atomicturtle

Copy link
Copy Markdown
Contributor Author

Addressed the non-blocking review notes:

  1. `shipped_package_names_for_product`: calls `AdvisoryPackage._clean_package_name()` (also made it a `@staticmethod` with a single `module.` strip) so cleaning cannot drift from the model.
  2. Bulk upsert: left the per-row path for now (as suggested for infrequent Temporal runs) with a comment to switch to `INSERT ... ON CONFLICT` if classify of ~12k CVEs/product is slow in practice.

Also rebased onto current `main`. Ready once #91 lands.

This branch has not been deployed

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