What did you do? (required. The issue will be closed when not provided.)
Scanned an Ubuntu 24.04 (noble) host that is attached to Ubuntu Pro with esm-apps + esm-infra enabled and fully up to date, using vuls scan (fast mode) + vuls report with the Vuls2 DB (ghcr.io/vulsio/vuls-nightly-db:0, fetched 2026-08-20).
Many installed packages are ESM builds, e.g. freeglut 3.4.0-1ubuntu0.1~esm1, ffmpeg 7:6.1.1-3ubuntu5+esm10, openexr 3.1.5-5.1ubuntu0.1~esm1, python-pip 24.0+dfsg-1ubuntu1.3+esm3, cjson 1.7.17-1ubuntu0.1~esm3, mbedtls 2.28.8-1ubuntu0.1~esm1.
What did you expect to happen?
CVEs whose fix was published in the esm-apps / esm-infra pocket and whose fixed version is already installed should not be reported as notFixedYet: true, fixState: needed.
Ground truth from Canonical for one example (freeglut, CVE-2024-24258):
$ pro fix --dry-run CVE-2024-24258
CVE-2024-24258: Freeglut vulnerabilities
1 affected source package is installed: freeglut
(1/1) freeglut:
A fix is available in Ubuntu Pro: ESM Apps.
The update is already installed.
✔ CVE-2024-24258 is resolved.
and https://ubuntu.com/security/cves/CVE-2024-24258.json for noble: status: released, fixed version 3.4.0-1ubuntu0.1~esm1, pocket: esm-apps.
What happened instead?
The report marks the CVE as unfixed, sourced from the plain noble_medium segment of the ubuntu-cve-tracker:
"CVE-2024-24258": {
"affectedPackages": [
{"name": "libglut-dev", "notFixedYet": true, "fixState": "needed"},
{"name": "libglut3.12", "notFixedYet": true, "fixState": "needed"}
],
"cveContents": {"ubuntu_api": [{"type": "ubuntu_api",
"optional": {"vuls2-sources": "[{\"root_id\":\"CVE-2024-24258\",\"source_id\":\"ubuntu-cve-tracker\",\"segment\":{\"ecosystem\":\"ubuntu:24.04\",\"tag\":\"noble_medium\"}}]"}}]}
}
"packages": {"libglut3.12": {"name": "libglut3.12", "version": "3.4.0-1ubuntu0.1~esm1"}}
"SrcPackages": {"freeglut": {"name": "freeglut", "version": "3.4.0-1ubuntu0.1~esm1", "binaryNames": ["libglut3.12", "libglut-dev"]}}
Scale of the problem on this host: of 266 "open" userspace CVE×source-package entries in the report, 60 are already fixed by an installed ESM build (checked against the Ubuntu CVE tracker JSON, noble status released, pocket esm-*, fixed version <= installed source version with dpkg --compare-versions): ffmpeg 34 of 38 reported CVEs, mbedtls 5, zvbi 5, cjson 4, openexr 3, python-pip 3, freeglut 2, qtwebengine-opensource-src 1, qtdeclarative-opensource-src 1, gst-plugins-bad1.0 1, wheel 1.
Why (as far as I can tell from the code)
In the ubuntu-cve-tracker data there are two segments per release for such packages: the plain noble_<prio> segment, where the status is needed (the ~esm build is not available to non-Pro users), and the esm-apps/noble_<prio> segment, where the status is released (3.4.0-1ubuntu0.1~esm1).
detector/vuls2/vuls2.go (walkVulnerabilityDetections) evaluates every segment independently and records the match per source{RootID, SourceID, Segment}. The esm-apps/noble segment does not match (installed >= fixed), the plain noble segment matches with an unfixed needed status, so the CVE surfaces as open. ignoreCriterion in detector/vuls2/vendor.go only drops non-ESM /-prefixed tags (fips, …) and keeps both the plain and the ESM segment; compareTag additionally prefers the plain tag (!strings.Contains(tag, "/") → 2) over the ESM one when choosing contents. Nothing ties the two segments of the same package together, and the scanner does not know/care whether the host is Pro-attached.
Proposal
For ecosystem ubuntu:*, source ubuntu-cve-tracker: when a package is detected as unfixed in the plain <release>_* segment but the same source package has a released status in an esm-apps/<release>_* / esm-infra/<release>_* (or esm, *-legacy, ros-esm) segment whose fixed version is <= the installed version, drop the plain-segment match (the fix is installed). Cheap heuristics that would already cover the real world: the installed version string contains esm (~esmN / +esmN), or the host has /etc/apt/sources.list.d/ubuntu-esm-apps.sources / pro status reports esm-apps: enabled (could be collected at scan time like other host facts). Conversely, for a non-Pro host the ESM released status could be surfaced as "fix available in Ubuntu Pro" instead of being invisible.
Steps to reproduce the behaviour
- Ubuntu 24.04 host,
pro attach …, pro enable esm-apps, apt install libglut3.12 (gets 3.4.0-1ubuntu0.1~esm1).
vuls scan (fast mode is enough), vuls report -format-json with the Vuls2 nightly DB.
CVE-2024-24258 / CVE-2024-24259 are reported with notFixedYet: true, fixState: needed for libglut3.12, while pro fix --dry-run CVE-2024-24258 says the fix is already installed.
Configuration (MUST fill this out):
Hash : vuls-v0.40.1-build-20260730_021743_e6624e9 (vuls -v)
[vuls2]
path = "/vuls/db/vuls.db"
repository = "ghcr.io/vulsio/vuls-nightly-db:0"
skipUpdate = true
[default]
port = "22"
user = "vuls-scan"
keyPath = "/vuls/ssh/id_ed25519"
scanMode = ["fast"]
scanModules = ["ospkg"]
[servers]
[servers.host]
host = "…"
vuls scan -config /vuls/config.toml -results-dir /vuls/results
vuls report -config /vuls/config.toml -results-dir /vuls/results -to-localfile -format-json -format-full-text -format-list -lang=en
What did you do? (required. The issue will be closed when not provided.)
Scanned an Ubuntu 24.04 (noble) host that is attached to Ubuntu Pro with
esm-apps+esm-infraenabled and fully up to date, usingvuls scan(fast mode) +vuls reportwith the Vuls2 DB (ghcr.io/vulsio/vuls-nightly-db:0, fetched 2026-08-20).Many installed packages are ESM builds, e.g.
freeglut 3.4.0-1ubuntu0.1~esm1,ffmpeg 7:6.1.1-3ubuntu5+esm10,openexr 3.1.5-5.1ubuntu0.1~esm1,python-pip 24.0+dfsg-1ubuntu1.3+esm3,cjson 1.7.17-1ubuntu0.1~esm3,mbedtls 2.28.8-1ubuntu0.1~esm1.What did you expect to happen?
CVEs whose fix was published in the
esm-apps/esm-infrapocket and whose fixed version is already installed should not be reported asnotFixedYet: true, fixState: needed.Ground truth from Canonical for one example (freeglut, CVE-2024-24258):
and https://ubuntu.com/security/cves/CVE-2024-24258.json for
noble:status: released, fixed version 3.4.0-1ubuntu0.1~esm1, pocket: esm-apps.What happened instead?
The report marks the CVE as unfixed, sourced from the plain
noble_mediumsegment of the ubuntu-cve-tracker:Scale of the problem on this host: of 266 "open" userspace CVE×source-package entries in the report, 60 are already fixed by an installed ESM build (checked against the Ubuntu CVE tracker JSON,
noblestatusreleased, pocketesm-*, fixed version<=installed source version withdpkg --compare-versions): ffmpeg 34 of 38 reported CVEs, mbedtls 5, zvbi 5, cjson 4, openexr 3, python-pip 3, freeglut 2, qtwebengine-opensource-src 1, qtdeclarative-opensource-src 1, gst-plugins-bad1.0 1, wheel 1.Why (as far as I can tell from the code)
In the ubuntu-cve-tracker data there are two segments per release for such packages: the plain
noble_<prio>segment, where the status isneeded(the~esmbuild is not available to non-Pro users), and theesm-apps/noble_<prio>segment, where the status isreleased (3.4.0-1ubuntu0.1~esm1).detector/vuls2/vuls2.go(walkVulnerabilityDetections) evaluates every segment independently and records the match persource{RootID, SourceID, Segment}. Theesm-apps/noblesegment does not match (installed >= fixed), the plainnoblesegment matches with an unfixedneededstatus, so the CVE surfaces as open.ignoreCriterionindetector/vuls2/vendor.goonly drops non-ESM/-prefixed tags (fips, …) and keeps both the plain and the ESM segment;compareTagadditionally prefers the plain tag (!strings.Contains(tag, "/")→ 2) over the ESM one when choosing contents. Nothing ties the two segments of the same package together, and the scanner does not know/care whether the host is Pro-attached.Proposal
For
ecosystem ubuntu:*, sourceubuntu-cve-tracker: when a package is detected as unfixed in the plain<release>_*segment but the same source package has areleasedstatus in anesm-apps/<release>_*/esm-infra/<release>_*(oresm,*-legacy,ros-esm) segment whose fixed version is<=the installed version, drop the plain-segment match (the fix is installed). Cheap heuristics that would already cover the real world: the installed version string containsesm(~esmN/+esmN), or the host has/etc/apt/sources.list.d/ubuntu-esm-apps.sources/pro statusreportsesm-apps: enabled(could be collected at scan time like other host facts). Conversely, for a non-Pro host the ESMreleasedstatus could be surfaced as "fix available in Ubuntu Pro" instead of being invisible.Steps to reproduce the behaviour
pro attach …,pro enable esm-apps,apt install libglut3.12(gets3.4.0-1ubuntu0.1~esm1).vuls scan(fast mode is enough),vuls report -format-jsonwith the Vuls2 nightly DB.CVE-2024-24258/CVE-2024-24259are reported withnotFixedYet: true, fixState: neededforlibglut3.12, whilepro fix --dry-run CVE-2024-24258says the fix is already installed.Configuration (MUST fill this out):
Go version (
go version): n/a (official imagevuls/vuls:v0.40.1)Go environment (
go env): n/aVuls environment:
Hash :
vuls-v0.40.1-build-20260730_021743_e6624e9(vuls -v)