fix(detector/vuls2): let only an Ubuntu build's own pocket judge it - #2650
Draft
MaineK00n wants to merge 1 commit into
Draft
fix(detector/vuls2): let only an Ubuntu build's own pocket judge it#2650MaineK00n wants to merge 1 commit into
MaineK00n wants to merge 1 commit into
Conversation
This was referenced Aug 27, 2026
MaineK00n
force-pushed
the
MaineK00n/ubuntu-pocket-lineage
branch
from
August 28, 2026 07:44
f28fd0f to
eab7d22
Compare
Fixes #2645. The ubuntu-cve-tracker states one release in several pockets that all land in the same ecosystem and are told apart only by the detection tag: the plain <release> tag for the archive, esm-apps/<release> and esm-infra/<release> (and their -legacy variants) for Ubuntu Pro, fips/<release> and fips-updates/<release> for FIPS. Every condition was evaluated on its own, so an installed version got compared against fixed versions from build lineages it never came from -- and those numbers do not order across pockets: 3.4.0-1ubuntu0.1~esm1 < 3.4.0-1ubuntu0.1 an archive build sorts ABOVE the esm-apps build that reserves the next archive version 1.0.2g-1ubuntu4.fips.4.20.9 > 1.0.2g-1ubuntu4.20+esm9 > 1.0.2g-1ubuntu4.20 a FIPS build sorts above both Three consequences, all reproducible against the nightly DB: * A universe package the archive never fixes stays "needed" in the plain pocket forever while esm-apps publishes the only fix. The ESM build carrying that fix was reported as vulnerable, because the esm-apps criterion simply did not match it and the plain pocket's "needed" was the only statement left (#2645: 60 such findings on one Pro-attached noble host). * Where both pockets publish a fix at different versions -- focal imagemagick CVE-2021-20224 is fixed at 8:6.9.10.23+dfsg-2.1ubuntu11.9 in the archive and at ...11.4+esm1 in esm-apps -- an installed ...11.4+esm1 is below the archive's version, so the plain pocket reported a package the ESM pocket had already fixed. * ignoreCriterion dropped every FIPS tag outright to keep non-FIPS hosts from being judged by FIPS statements. That left FIPS hosts judged by archive statements their builds sort above, silently clearing them, and pointed the ones that were reported at an archive fixed version they cannot install. Model the pockets as what they are -- separate build lineages -- and let exactly one of them judge each installed build: the first of its pocketFallbacks that says anything about the package. A build no candidate pocket speaks about is dropped from every criterion. * tagPocket resolves a tag to archive / esm / fips. The tracker's release keys put the service on either side of the slash (esm-apps/noble, but trusty/esm), so both are looked up. * installedPocket reads the pocket off Canonical's version convention (~esmN / +esmN / +esm.N, .fips. / +fips.N). The authoritative answer is the apt origin of the installed version, which the Ubuntu scanner does not collect yet -- MergeNewVersion overwrites Repository with the CANDIDATE version's repository whenever an update is pending, and the Debian scanner fills that from `apt-cache policy` with an apt suite. preConvertPkgs now carries Repository only for the ecosystems whose data gates on it (redhat, centos, amazon, alpine), an allowlist rather than a denylist so a family added later defaults to not gating -- that direction only ever loses filtering, never a detection. installedPocket should consult the field once a scanner reports the installed build's own origin. * pocketStatements collects, over all the sibling conditions, which pockets have a criterion that survives ignoreCriterion. That is what separates "this pocket says the build is fine" from "this pocket says nothing", and counting only usable criterions matters: 24,735 of the 25,666 plain-unfixed/esm-fixed pairs in the DB are "ignored: end of standard support", and treating those as an archive statement would stop the ESM statement being used at all on xenial and trusty. * pocketFallbacks orders the candidates. An Ubuntu Pro build is built on an archive one, and the Pro pockets continue the archive's builds once a release leaves standard support, so the two fall back to each other -- which is also what covers the Pro builds installedPocket cannot recognise (esm-infra republishes plain archive versions, carrying no marker: 17,117 of its 17,605 fixed statements). Nothing falls back INTO FIPS, so keeping the FIPS tags is now safe. ignoreCriterion's esm allowlist becomes "is this a pocket we know", which keeps dropping tags naming a pocket this build cannot match against an installed build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MaineK00n
force-pushed
the
MaineK00n/ubuntu-pocket-lineage
branch
from
August 28, 2026 07:45
eab7d22 to
2a740bc
Compare
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.
What did you implement:
Fixes #2645.
The
ubuntu-cve-trackerstates one release in several pockets that all land in the same ecosystem and are told apart only by the detection tag: the plain<release>tag for the archive,esm-apps/<release>andesm-infra/<release>(and their-legacyvariants) for Ubuntu Pro,fips/<release>andfips-updates/<release>for FIPS.walkVulnerabilityDetectionsevaluated every condition on its own, so an installed version got compared against fixed versions from build lineages it never came from. Those numbers do not order across pockets:Three consequences, all reproducible against the nightly DB:
1. The reported bug (#2645). A universe package the archive never fixes stays
neededin the plain pocket forever, whileesm-appspublishes the only fix.vuls db search root CVE-2024-24258 --datasource ubuntu-cve-tracker,ubuntu:24.04:esm-apps/noble_mediumfixed,< 3.4.0-1ubuntu0.1~esm1noble_mediumunfixed, vendorneeded(no range — matches every version)With
3.4.0-1ubuntu0.1~esm1installed the esm-apps criterion simply does not match, so the plain pocket'sneededis the only statement left and the build carrying the fix is reported as vulnerable. The reporter saw 60 such findings on one Pro-attached noble host.2. Both pockets fixed, at different versions.
ubuntu:20.04/ imagemagick / CVE-2021-20224:An installed
…11.4+esm1is below the archive's fixed version, so the plain pocket reported a package the ESM pocket had already fixed.3. FIPS hosts.
ignoreCriteriondropped every FIPS tag outright to keep non-FIPS hosts from being judged by FIPS statements. That left FIPS hosts judged by archive statements their builds sort above — silently clearing them — and pointed the ones that were still reported at an archive fixed version they cannot install.The change
Model the pockets as what they are — separate build lineages — and let exactly one of them judge each installed build: the first of its
pocketFallbacksthat says anything about the package. A build no candidate pocket speaks about is dropped from every criterion.tagPocketarchive/esm/fips/ unknown. The tracker's release keys put the service on either side of the slash (esm-apps/noble, buttrusty/esm), so both are looked upinstalledPocket~esmN/+esmN/+esm.N,.fips./+fips.N)pocketStatementsignoreCriterionpocketFallbacksesm→[esm, archive],archive→[archive, esm],fips→[fips, esm, archive]narrowToPocketnarrowToPocketis applied infilterCriterion, which already exists to narrowAccepts.Versionfor ecosystem-specific reasons (the running-kernel filter).ignoreCriterion's esm allowlist becomes "is this a pocket we know", so FIPS tags are kept and narrowed instead of dropped.Two details that matter:
ignored: end of standard support, whichignoreCriterionalready drops. Counting those as an archive statement would stop the ESM statement being used at all on xenial and trusty.fips-updates/jammy_lowexpectation inTest_postConvertis unchanged.models.Package.Repositorynow reaches the query only where the data gates on itThe authoritative pocket is the apt origin of the installed version. vuls does not report it:
models.Packages.MergeNewVersionoverwritesRepositorywith the candidate version's repository for every package with a pending update, in every family that scans updatables.scanner/debian.gofills that fromapt-cache policywith the candidate's suite (noble-updates/main), and only outsidefast/offlinescans.repoquery --pkgnarrow=installed --qf='… %{UI_FROM_REPO}', runs only for Amazon Linux 2 withyum-utilspresent.preConvertPkgsnow carriesRepositoryinto the vuls2 query only for the ecosystems whose data actually gates on it —redhat(centosresolves to theredhatecosystem too),amazon,alpine. An allowlist rather than a denylist, so a family added later, or a scanner that starts reporting something new, defaults to not gating; that direction only ever loses filtering, never a detection. Foralma/rocky/oracle/fedora/suse/debian/ubuntuit is a no-op or the fix, since none of their data sources emitrepositories.installedPocketshould consult the field once a scanner reports the installed build's own origin, keeping the version convention as the fallback forfast/offlinescans and older result JSON.This also guards against MaineK00n/vuls-data-update#953: without it, a candidate suite reaching the repository gate would filter out exactly the packages that have an update available. MaineK00n/vuls2#431 applies the same allowlist on the vuls2 CLI's own path, which never goes through
preConvertPkgs.Type of change
How Has This Been Tested?
Test_postConvertgains"ubuntu: a pocket only judges the builds installed from it", with the four situations above:2.8.1-6ubuntu0.1~esm1neededfixed <2.8.1-6ubuntu0.1~esm11.7.15-1(archive)neededfixed <1.7.15-1ubuntu0.1~esm1needed(unchanged)…22.04.1+esm1fixed <…22.04.5fixed <…22.04.1+esm13.0.2-0ubuntu1.10+fips.1fixed <3.0.2-0ubuntu1.12fixed <3.0.2-0ubuntu1.10+fips.2fixedIn: 3.0.2-0ubuntu1.10+fips.2Verified to have teeth: with the narrowing disabled and the FIPS drop restored, rows 1, 3 and 4 all fail.
Also added:
Test_tagPocket/Test_installedPocket, which pin the version convention — including that a marker-less Ubuntu Pro build (4.15.0-1146.161~14.04.1, asesm-infrarepublishes for CVEs fixed before a release left standard support) reads asarchiveand is covered bypocketFallbacksinstead. 17,117 ofesm-infra's 17,605 fixed statements are marker-less, so this is the normal case, not an edge one.Test_preConvertPkgscase for the dropped candidate suite.Every existing test passes with no expectation changed.
Known gaps
Neither is a regression; both need the installed build's apt origin (a scanner change) to close.
pocketFallbackskeeps them detected, but where the archive and ESM statements disagree the archive's is used. e.g.ubuntu:16.04/ linux / CVE-2020-12352 is4.4.0-197.229in the archive and4.4.0-262.296inesm-infra.esm-infravsesm-infra-legacy— separate pockets sharing one version convention, so they collapse intopocketESMand their statements are OR-ed. They disagree for 299 packages in the DB sample.Reference
gost/ubuntu.go— fix(detector/gost/ubuntu): detection logic when esm etc. are mixed #2090 fixed the same class of bug there, and feat!(detector): detect ubuntu with vuls2 #2271 dropped it. This PR differs from fix(detector/gost/ubuntu): detection logic when esm etc. are mixed #2090 deliberately in its case 3 (an archive build sorting above the ESM fixed version, with the plain pocket stillneeded): fix(detector/gost/ubuntu): detection logic when esm etc. are mixed #2090 treated that as fixed, this reports it, because that host is running an archive build the archive has no fix for.pkg/scan/scan.goconverts vuls0 result JSON without going throughpreConvertPkgs, so it needs the same dropChecklist:
make fmtmake testIs this ready for review?: NO
🤖 Generated with Claude Code