Skip to content

Collapse OSV advisories that describe the same CVE - #23

Merged
dpage merged 1 commit into
mainfrom
fix-duplicate-advisories
Sep 22, 2026
Merged

dpage merged 1 commit into
mainfrom
fix-duplicate-advisories

Conversation

@dpage

@dpage dpage commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Two bugs in the OSV importer, both visible on https://www.pgadmin.org/security/ today.

Every advisory is listed twice. OSV returns one record per source, so each CVE arrives as both a GHSA and a PYSEC record: a query today returns 56 records for 28 CVEs, exactly doubled, and the live page shows all 56. fetch_advisories() now collapses records sharing a CVE, keeping the GHSA one. That choice is not cosmetic: the identifier is what fetch_pgadmin_cves upserts on, and the PYSEC identifiers for pgAdmin have all been reassigned within the past year for CVEs going back to 2022, so keying on those would churn the table whenever that happens again. References and aliases are unioned rather than taken from the winner alone, so no link is lost and the dropped identifier still matches a search. Records with no CVE pass through untouched.

Twenty of the twenty eight have no score. Every advisory published since the middle of 2026 carries both a CVSS 4.0 vector and a 3.1 one, and severity extraction deliberately took the highest version present. We cannot compute a 4.0 base score, its scoring being a lookup table rather than a formula and this module having no dependencies by design, so those advisories showed no score at all despite a perfectly scorable 3.1 vector sitting beside the one we kept. Worse, the page orders by base score, so the newest vulnerabilities sorted as though they were the least severe. The vector and the score now come from the same entry, the highest version that actually yields a number.

After deploying, run ./manage.py fetch_pgadmin_cves --prune once. The redundant rows are already in the database, and pruning is what removes them.

Verified against the live OSV response: 56 records in, 28 out, no CVE appearing twice, every survivor a GHSA, references a superset of both sources, and every advisory now carrying a base score and a severity band.

No test is included because the repository has none and this did not seem the place to introduce the convention; happy to add security/tests.py if you would like one.

OSV returns one record per source, so every pgAdmin vulnerability arrives
twice, once from the GitHub Advisory Database and once from the PyPA database,
and the security page lists each of them twice: a query today returns 56
records for 28 CVEs, exactly doubled.

The two carry the same summary, details and severity, so the merge keeps the
GHSA record and drops the other. GHSA wins because GitHub assigns an advisory
an identifier and keeps it, whereas the PYSEC identifiers for pgAdmin have all
been reassigned within the past year for CVEs going back to 2022, and the
identifier is what we upsert on.

References and aliases are unioned rather than taken from the winner alone,
since the discarded record links to a couple of places the other does not, and
its identifier is how somebody searching for it still finds the advisory.
@dpage
dpage merged commit 1884cdd into main Sep 22, 2026
5 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.

1 participant