Skip to content

feat(ubuntu): capture Notes section from Ubuntu security data (#1126)#1163

Open
ChrisJr404 wants to merge 1 commit into
anchore:mainfrom
ChrisJr404:feat/ubuntu-capture-notes-1126
Open

feat(ubuntu): capture Notes section from Ubuntu security data (#1126)#1163
ChrisJr404 wants to merge 1 commit into
anchore:mainfrom
ChrisJr404:feat/ubuntu-capture-notes-1126

Conversation

@ChrisJr404

Copy link
Copy Markdown

What

Closes #1126.

The Ubuntu security tracker entries include a Notes: section where Canonical analysts add free-form context: why a package isn't affected, why a fix is deferred, the rationale for a priority assignment, mitigation observations, and so on. The vunnel provider parses Ubuntu CVE files but currently discards everything in this section.

This PR captures that content end-to-end:

  • parse_notes() parses the Notes: block into (author, text) pairs.
  • A new Note dataclass carries each note on the in-memory CVEFile.
  • Notes survive the asdict / orjson dump → load round trip used by _merge_cve / _load_merged_cve.
  • map_parsed() attaches them to each affected-namespace Vulnerability record so the JSON written by the provider includes them, ready for grype (or any other consumer of the os vulnerability schema) to surface alongside findings.

Format handled

Notes:
 mdeslaur> first line of a note
  continuation of the same note (indented further)
 sbeattie> another note
 > an authorless note
Mitigation:

The parser tolerates missing author prefixes, blank intra-section lines, and continuation lines on any indent depth deeper than the author line.

Output shape

When the upstream entry has notes, the produced JSON gains a Notes field on the Vulnerability object:

{
  "Vulnerability": {
    "Name": "CVE-2024-3094",
    "NamespaceName": "ubuntu:24.04",
    "Notes": [
      {
        "author": "mdeslaur",
        "text": "The affected version of xz-utils was only in noble-proposed, and was removed before migrating to noble itself. No released versions of Ubuntu were affected by this issue."
      },
      {
        "author": null,
        "text": "Priority reason: Results in a backdoor in sshd"
      }
    ],
    "...": "..."
  }
}

The Notes key is only emitted when at least one note was parsed. Empty Notes: blocks (the common case) leave the existing record shape untouched, which means existing snapshots in this repo still match and downstream consumers don't see a churn of empty arrays. The os vulnerability schema does not pin additionalProperties, so this is additive without a schema bump.

The grype-side schema is intentionally not changed in this PR — the issue calls out that grype consumption is a follow-up, and this PR just gets the data flowing into the vunnel intermediate.

Tests

Added eight unit tests covering:

  • empty Notes: block (yields [])
  • single authored note with continuation lines
  • multiple notes with mixed authored / authorless entries
  • end-to-end parse of a fixture CVE file with a populated Notes: block (example_ubuntu_cve_with_notes)
  • the existing example_ubuntu_cve fixture (empty Notes) still parses to notes == []
  • asdict / from_dict round trip preserves notes
  • map_parsed emits Notes on the JSON record when present
  • map_parsed omits Notes from the JSON record when no notes were parsed (snapshot stability)

The existing snapshot test (test_provider_via_snapshot) still passes against the unmodified snapshots since none of the fast-export fixtures have populated notes.

$ uv run pytest tests/unit/providers/ubuntu/ -q
46 passed in 0.69s
$ uv run pytest tests/unit/ -q
834 passed in 2.86s

Test plan

  • uv run pytest tests/unit/providers/ubuntu/ — 46 / 46 pass
  • uv run pytest tests/unit/ — 834 / 834 pass
  • uv run ruff check src/vunnel/providers/ubuntu/parser.py tests/unit/providers/ubuntu/test_ubuntu.py — only pre-existing project-wide warnings (S101 pytest assertions, A001 in unrelated tests); no new errors introduced
  • uv run ruff format applied
  • Commit signed off (DCO)

…e#1126)

The Ubuntu security tracker format includes a free-form Notes: block where
Canonical analysts record context like why a package isn't affected, why a
fix is deferred, mitigation observations, etc. The provider was throwing
this away.

This change parses each note in the Notes: section into a (author, text)
tuple, carries it on the in-memory CVEFile, persists it through the merged
JSON written to disk, and includes it in the Vulnerability record produced
for each affected namespace so grype (or any other consumer of the os
schema output) can surface the analyst's commentary next to findings.

The Notes attribute is only emitted on the JSON record when at least one
note was parsed. Empty Notes: blocks (the common case) leave the existing
record shape unchanged, so this is a non-breaking addition for downstream
consumers.

Notes block format handled:

  Notes:
   author> first line of the note
    continuation of the same note
   author2> another note
   > authorless note

The parser tolerates missing author prefixes, trailing blank lines, and
notes that span any number of continuation lines.

Signed-off-by: ChrisJr404 <chris@hacknow.com>
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.

Capture notes section from Ubuntu security data

1 participant