Repository navigation
feat(scan): judge each CVE against the installed version - #58
Merged
Merged
Conversation
A scan found the CVEs that name a product and could not say which affect what is installed: for Notepad++ 8.5.0 the recorded NVD answer holds 21, 11 of them about other versions or another product, and all 21 were listed and ranked. affected.py could answer and waited for the watchlist columns of "the versionradar design, section 5", a text never committed. - docs/DESIGN.md rebuilds that design from what the code committed to. - Five nullable watchlist columns (cpe, vendor, product_id, installed_version, channel), migrated into existing databases. - `add --version --cpe`: the CPE typed by a person and checked for form (notepad++ is refused with NVD's notepad\+\+), a version refused when it cannot be ordered. - affected.judge: affected, not affected or not evaluable, from the NVD record's own configurations, which nvd._parse_item now keeps. Cannot tell never becomes not affected. - scan lists affected and not evaluable, --all the rest; it gives the split, what an update closes, and always the NVD caveat; entries without a version are scanned by name and named. Written test first and seen failing; the guards added after the first green run each kill their mutant, 26 of 26. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| if fields: | ||
| # Column names from the literal keys above, never from input. | ||
| assignments = ", ".join(f"{column} = ?" for column in fields) | ||
| await db.execute(f"UPDATE watchlist SET {assignments} WHERE name = ?", |
Merging this PR will not alter performance
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Audit finding PR-01 (critical) of 2026-10-17, first step: the scan judges CVEs against the installed version.
What was wrong
A scan found the CVEs that name a product and could not say which affect what is installed. The README said "tells you which vulnerabilities affect it". For Notepad++ the recorded NVD answer holds 21 CVEs; for 8.5.0, 11 of them concern other versions or another product, and all 21 were listed and ranked as work to do.
affected.pyalready knew how to answer (since 2026-09-28) and was deliberately not wired in, waiting for the watchlist columns of "the versionradar design, §5". That text was never committed and could not be found anywhere (E:\Dev, WSL, git history, notes).What changes
docs/DESIGN.md: the design the code referred to, rebuilt from whataffected.py,inventory.pyandtest_priority_wiring.pyalready committed to. §5 covers the columns, the three verdicts, what the scan prints, what is stored and the order of work (01a, 01b, 01c). The three references in the code now point to it.Watchlist: five nullable columns with no default (
cpe,vendor,product_id,installed_version,channel), migrated into existing databases.patchradar add <name> --version <v> --cpe <cpe>:affected.pycannot order;notepad++is refused with NVD'snotepad\+\+shown, because NVD would match nothing and the scan would read as clean.cpe.py).affected.judge: affected, not affected or not evaluable, from the record's own NVDconfigurations, whichnvd._parse_itemnow keeps (an empty list while NVD has not analysed the CVE). "Cannot tell" never becomes "not affected". This covers:Range.comparableseparates "outside the range" from "cannot be ordered", andclosed_byis factored out ofsummarise.scan:--alladds not affected;listshows version and CPE.Not in this PR, per DESIGN §5.6:
import(PR-01c).Tests (strict TDD)
test_cpe.py;test_watchlist_versions.py, with a hand-written pre-migration database;test_affected_verdict.py, on the recorded Notepad++ NVD payload. It agrees withsummarise: 10 affected and 11 not affected at 8.5.0, five fixes at 8.9.5;test_scan_versioned.py, a full CLI scan against the same recording replayed with respx: MSRC 404, the KEV conftest catalogue. Derived variants (configurations removed, payload reduced to the affected ten) are declared in each test.comparable,--allwith nothing hidden, caveat on an empty answer, 5 of 5, set nothing) each kill their mutant: 26/26 mutants killed.test_cli_escaping.py:addcalled as a function now passes its new options. Thelisttest no longer stubsget_watchlist: the hostile row is written straight into the test database, the way an older version left it.🤖 Generated with Claude Code