Skip to content

feat: check the SBOM against cve-status verdicts, resolved like an application - #9799

Merged
manolo merged 2 commits into
mainfrom
cve-status-verdicts
Nov 3, 2026
Merged

manolo merged 2 commits into
mainfrom
cve-status-verdicts

Conversation

@manolo

@manolo manolo commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Why

cveWhiteList in scripts/generateAndCheckSBOM.js has three problems:

  • It is keyed by purl@exact version. A false positive we already analysed goes red again on the next bump of the dependency.
  • Each branch has its own copy, and the copies disagree. main has 27 entries, 24.9 has 42 and 23.6 has 7.
  • Every verdict is written twice: once in cve-status and once here.

vaadin/cve-status publishes its verdicts at https://vaadin.github.io/cve-status/assessments.json. The URL is public and needs no token. Each entry has three parts:

  • the package purl, without a version;
  • the advisory ids, with their aliases;
  • affects, a range of platform versions, such as >=24.4,<24.7.

What

At build time the check downloads that list with curl, using the same pattern as downloadSbom. A finding is known when either list covers it:

  • the local cveWhiteList, using exactly today's rule;
  • the cve-status list, when all of these hold:
    • the purl, decoded and without its version, matches a verdict;
    • the version being built (currVersion) is inside that verdict's affects;
    • every id the scanners reported is named by those verdicts.

A new CVE on the same package therefore still turns the build red. Only verdicts that silence a finding appear in the list (false_positive, not_affected, configuration, no_risk, fixed), so risk stays red.

If the download fails, the JSON does not parse, or the schema is unknown, the check logs it and falls back to the local list alone. That is today's behaviour.

The matching functions are copied unchanged from scripts/platform/known-vulnerabilities.js. That file is tested there against the Python that writes the verdicts. Fixes belong there, and are then copied here.

The tree being checked is the application's

The check only means something if both sides look at the same dependency tree. Until now they did not:

  • vaadin-platform-sbom declared everything directly, with no Spring Boot.
  • cve-status scans an application shaped like the starters: it inherits spring-boot-starter-parent, imports vaadin-bom, uses vaadin-spring-boot-starter and hilla-spring-boot-starter, and gets copilot through vaadin-dev.

This is why the build reported packages such as guava 33.5.0/33.6.0 or tomcat-catalina, which no application resolves.

The pom now has the same shape:

  • spring-boot-dependencies (${spring.boot.version}) is imported after vaadin-bom. That reproduces a real application's precedence: what vaadin-bom manages wins because the application declares it, and Spring Boot decides everything else.
  • vaadin-spring and hilla are replaced by their starters.
  • copilot now comes in through vaadin-dev and is no longer declared directly.
  • The starter's own spring-boot-starter-validation and spring-boot-devtools are added, and spring-boot-starter-test is added at test scope.

I resolved both trees against 25.4.0-alpha4 and Spring Boot 4.1.2 with dependency:list, runtime scope:

  • 319 of 320 artifacts are identical.
  • The one difference is slf4j-api and jul-to-slf4j: 2.0.17 here (from the slf4j-bom inside vaadin-bom) against 2.0.20 in the application (Spring Boot's).

This changes the Software.Bill.Of.Materials.json that 25.4 publishes. From now on it describes what an application deploys, not the union of every artifact Vaadin declares.

Verified

The patched checkVunerabilities was run on the findings printed by three of today's runs:

Run Red with the local list (main's) Red with the local list + cve-status Download fails
24.7.19, https://github.com/vaadin/platform/actions/runs/41500369030 52 27 52
23.6.19, https://github.com/vaadin/platform/actions/runs/41507903539 41 25 41
25.3.5, https://github.com/vaadin/platform/actions/runs/41522330996 0 0 0

What stays red has two causes:

  • risk verdicts. These are mostly Spring, Tomcat and Logback on 24.7 and 23.6, and they are real.
  • Packages this build scans and cve-status does not, such as tomcat-catalina, spring-webflux, vite-plus and log4j-to-slf4j.

After this

  • Backport to 25.3, 25.2, 24.10, 24.9, 24.7, 24.4, 23.6 and 14.14. Tags restore scripts/ from their branch, so each branch needs the change.
  • Remove local entries once cve-status covers them. cve.py whitelist-json --branch <b> lists the ones it does not cover yet.

Related to https://github.com/vaadin/cve-status/pull/284

🤖 Generated with Claude Code

The SBOM check now also reads https://vaadin.github.io/cve-status/assessments.json.
A finding counts as known when every id it reports is named by a cve-status verdict
on its versionless purl, and the verdict's affects range covers the platform version
being built.

The local cveWhiteList stays: a finding either list covers is known, and if the fetch
fails or the schema is unknown the check uses the local list alone. Nothing that
passes today fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Dependencies Report

  • 🚫 Vulnerabilities:

    • Vulnerabilities in: pkg:javascript/quill@2.0.3 [CVE-2025-15056] (owasp)
      · cpe:2.3:a:slab:quill:2.0.3:::::node.js::
  • 🟠 Known Vulnerabilities:

    • Vulnerabilities in: pkg:maven/io.opentelemetry/opentelemetry-api@1.62.0 [CVE-2026-118259, CVE-2026-54285] (osv-bomber,osv-scan,owasp)
      👌 [cve-status] Your scanner has matched the wrong product. The CPE it used, opentelemetry:opentelemetry, names the project rather than a package and carries the platform each record is about: CVE-2026-54285 is an advisory of opentelemetry-js on node.js, and the other four are advisories of the Go implementation. None is about a Java artifact, but the Java libraries share the product name, so each lands on every io.opentelemetry jar your application resolves. The range is open because the claim is about which implementation the records name, which no Java version changes. Nothing to upgrade for these. The parser is in the jar and nothing in a Vaadin application hands it an incoming header. From 25.3, opentelemetry-api 1.62.0 arrives through TestBench, whose Selenium client only adds trace context to the requests it sends, and Observability Kit no longer uses OpenTelemetry or an agent. The advisory needs incoming tracestate headers to reach W3CTraceContextPropagator.extract, which happens only if you add tracing of your own: Spring Boot OpenTelemetry tracing, the OpenTelemetry Java agent, or code that extracts trace context from requests.
      ·
      · cpe:2.3:a:opentelemetry:opentelemetry::::::node.js::*
    • Vulnerabilities in: pkg:npm/highcharts@12.2.0 [CVE-2026-118246, CVE-2026-118251, CVE-2026-118244, CVE-2026-116796, CVE-2026-118250] (osv-bomber,oss-bomber,osv-scan)
      👌 Fixed in Vaadin Charts without bumping the bundled Highcharts (announced as CVE-2026-107588): fix: skip unsupported values in chart options web-components#12886, cherry-picked to 25.1, 25.2 and 25.3, ignores reserved segments in series.keys and point option names, credits links without a supported URL scheme and event attribute names in style options applied as SVG attributes, and parses text markup in an inert document when the default parser fails. Scanners keep flagging 12.2.0 by version only. The bump to Highcharts 12.6.2 (feat: upgrade Highcharts to 12.6.2 web-components#13289) replaces these patches with the upstream fixes and clears the alert.
      ·
    • Vulnerabilities in: pkg:npm/picomatch@4.0.7 [CVE-2026-112366] (oss-bomber)
      👌 Build-time only: picomatch is pulled in by vite, rolldown and vite-plugin-checker and is not shipped in production bundles. The ReDoS requires an attacker supplied extglob pattern such as +(*), while the globs come from the developer's own build configuration. No fixed version is published on npm yet (4.0.7 is latest); upgrade once available.
      ·
    • Vulnerabilities in: pkg:npm/lerc@3.0.0 [CVE-2026-10758] (oss-bomber)
      👌 Not affected: lerc arrives through ol -> geotiff and is only used to decode LERC compressed GeoTIFF imagery. Vaadin Map does not expose a GeoTIFF source, so the decoder is never on the execution path; worst case impact would be a crashed browser tab. vulnerable_code_not_in_execute_path.
      ·
    • Vulnerabilities in: pkg:maven/me.friwi/jcef-api@jcef-ca49ada%2Bcef-135.0.20%2Bge7de5c3%2Bchromium-135.0.7049.85 [CVE-2024-21639, CVE-2024-21640, CVE-2024-9410] (owasp)
      👌 Wait for the update from the jcefmaven community. Meanwhile the swing-kit is supposed to be used with fixed websites and not to browse the internet, we have a check for that, so the only possible attacker would be the same person that created the swing application, aka our customer devs. so this vulnerability is not classified by us as critical issue
      · cpe:2.3:a:chromiumembedded:chromium_embedded_framework::::::::
      · cpe:2.3:a:ada:ada::::::::
    • Vulnerabilities in: pkg:maven/org.jetbrains.kotlin/kotlin-stdlib@2.3.21 [CVE-2026-53914] (owasp)
      👌 [cve-status] Your scanner has matched the wrong artifact. The advisory is unsafe deserialization of the incremental cache of KAPT, the annotation processing plugin of the Kotlin build tooling, and the advisory database names only org.jetbrains.kotlin:kotlin-gradle-plugin. The CPE jetbrains:kotlin covers every artifact JetBrains publishes under that name, so the scanner reported it on kotlin-stdlib, which does not contain that code. The range is open because no version of kotlin-stdlib carries it. Nothing to upgrade for it.
      · cpe:2.3:a:jetbrains:kotlin::::::::
    • Vulnerabilities in: pkg:maven/org.springframework.boot/spring-boot-devtools@4.1.2 [CVE-2022-31691] (owasp)
      👌 [cve-status] Your scanner has matched the wrong product. This advisory is about Spring Tools 4 for Eclipse and the Spring Boot Tools extension for VSCode, which are editor tooling, and the dependency it was matched against is spring-boot-devtools, a different artifact that no editor ships. Nothing in a Vaadin application is affected, and nothing has to be upgraded for it.
      · cpe:2.3:a:vmware:bosh_editor::::::::
      · cpe:2.3:a:vmware:cloudfoundry_manifest_yml_support::::::::
      · cpe:2.3:a:vmware:concourse_ci_pipeline_editor::::::::
      · cpe:2.3:a:vmware:spring_boot_tools::::::::
      · cpe:2.3:a:vmware:spring_tools::::::eclipse::*
    • Vulnerabilities in: pkg:maven/com.vaadin/vaadin-swing-kit-flow@3.0.1 [CVE-2021-33604] (owasp)
      👌 false report: this CVE is targeting Vaadin version prior 20, swing-kit-flow is using vaadin 24+ version, the related issue has been fixed.
      · cpe:2.3:a:vaadin:flow-server::::::::
      · cpe:2.3:a:vaadin:vaadin::::::::
  • 📔 No Core License Issues

  • 📔 No License Issues

  • 🟠 Changes in 25.4-SNAPSHOT since V25.4.0-alpha4

    • 36 packages added (29 external, 7 vaadin)
    • 141 packages modified (67 external, 74 vaadin)
    • 438 packages same (286 external, 152 vaadin)

[Click for more Details]

vaadin-platform-sbom now has the shape of the application vaadin/cve-status scans:
- spring-boot-dependencies is imported after vaadin-bom;
- vaadin-spring-boot-starter and hilla-spring-boot-starter replace vaadin-spring and hilla;
- vaadin-dev brings copilot, instead of copilot being declared directly;
- the starter's own spring-boot-starter-validation, devtools and test are added.

The CVE check therefore reports what a customer deploys, and the verdicts published
there apply to it.

Resolved against 25.4.0-alpha4 and Spring Boot 4.1.2, the runtime tree matches that
application's in 319 of 320 artifacts. The one difference is slf4j-api and jul-to-slf4j,
at 2.0.17 here and 2.0.20 there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@manolo manolo changed the title feat: read CVE verdicts from cve-status in the SBOM check feat: check the SBOM against cve-status verdicts, resolved like an application Nov 3, 2026
@manolo
manolo merged commit 786b80f into main Nov 3, 2026
8 of 12 checks passed
@manolo
manolo deleted the cve-status-verdicts branch November 3, 2026 12:39
manolo added a commit that referenced this pull request Nov 3, 2026
…plication [25.3] (#9804)

* feat: check the SBOM against cve-status verdicts, resolved like an application (#9799)

* feat: read CVE verdicts from cve-status in the SBOM check

The SBOM check now also reads https://vaadin.github.io/cve-status/assessments.json.
A finding counts as known when every id it reports is named by a cve-status verdict
on its versionless purl, and the verdict's affects range covers the platform version
being built.

The local cveWhiteList stays: a finding either list covers is known, and if the fetch
fails or the schema is unknown the check uses the local list alone. Nothing that
passes today fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: resolve the SBOM project the way a Spring Boot application does

vaadin-platform-sbom now has the shape of the application vaadin/cve-status scans:
- spring-boot-dependencies is imported after vaadin-bom;
- vaadin-spring-boot-starter and hilla-spring-boot-starter replace vaadin-spring and hilla;
- vaadin-dev brings copilot, instead of copilot being declared directly;
- the starter's own spring-boot-starter-validation, devtools and test are added.

The CVE check therefore reports what a customer deploys, and the verdicts published
there apply to it.

Resolved against 25.4.0-alpha4 and Spring Boot 4.1.2, the runtime tree matches that
application's in 319 of 320 artifacts. The one difference is slf4j-api and jul-to-slf4j,
at 2.0.17 here and 2.0.20 there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 786b80f)

* fix: judge a snapshot SBOM by the newest release of its line

25.3-SNAPSHOT compared as the start of the 25.3 line, so a cve-status verdict
saying a fix shipped in 25.3.5 did not apply to it. The SBOM run of
#9804 was red on Quill CVE-2025-15056
for that reason. A snapshot is now judged as prev.lastPatch, the newest release
of its line, which the same script already computes for the comparison.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.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.

1 participant