Skip to content

Attach a CycloneDX SBOM of libcobj.jar to every release - #893

Open
yutaro-sakamoto wants to merge 1 commit into
opensourcecobol:developfrom
yutaro-sakamoto:sbom-release-upstream
Open

Attach a CycloneDX SBOM of libcobj.jar to every release#893
yutaro-sakamoto wants to merge 1 commit into
opensourcecobol:developfrom
yutaro-sakamoto:sbom-release-upstream

Conversation

@yutaro-sakamoto

Copy link
Copy Markdown
Contributor

概要

リリースに libcobj.jar の SBOM (CycloneDX 1.6) を libcobj-sbom.jsonlibcobj-sbom.xml の 2 つの形式で添付します。生成には CycloneDX Gradle プラグインの最新版 3.4.1 を使用しています。

libcobj.jar は shadow jar (fat jar) であるため、同梱されているサードパーティ製ライブラリを jar 自体から特定することができません。SBOM を添付することで、利用者が Trivy・Grype・Dependency-Track 等の脆弱性スキャナに読み込ませられるようになります。

生成される SBOM には推移的依存を含む全ランタイム依存が、ハッシュとライセンス情報つきで列挙されます。includeConfigsruntimeClasspath に限定しているため、JUnit や Testcontainers といったテスト専用の依存は含まれません。

サードパーティ製 GitHub Actions は追加していません

SBOM は anchore/sbom-action のような外部 Action ではなく、CycloneDX Gradle プラグインで生成しています。ワークフロー側で使っているのは、既に使用中の actions/upload-artifactactions/download-artifact (どちらも GitHub 公式) だけです。

SBOM を生成する場所

libcobj.jar を生成しているのと同じ windows-build ジョブで生成しています。両者が必ず同じビルドの成果物になるためです。

また、生成ステップには意図的に if: ${{inputs.upload-artifacts}} を付けていません。push・pull request のたびに実行されることで、SBOM の設定が壊れたことがタグを打つまで発覚しない、という事態を防いでいます。

Gradle wrapper を 8.2.1 から 8.14.5 に更新しています

これは本 PR で唯一の付随的な変更ですが、必須でした。理由は 2 つあります。

  1. CycloneDX Gradle プラグイン 3.x 系は Gradle 8.4 以上を要求します。
  2. Gradle 8.2.1 に同梱されている ASM は Java 21 のクラスファイル (major version 65) を読めないため、最近の CycloneDX プラグインが引き込む jackson-core のマルチリリース jar を buildscript classpath に載せる段階で、configuration フェーズから失敗します。

プラグインを古いバージョン (1.8.x, 2023 年) に固定すれば回避できますが、Dependabot の次の bump で即座に壊れます。なお Gradle 8.2.1 は公式に Java 21 をサポートしておらず、CI は以前から Java 21 を使用しています。

gradlewgradlew.batgradle-wrapper.jar の差分は ./gradlew wrapper が再生成する標準の成果物です。wrapper jar の SHA-256 は Gradle 公式が公開している 8.14.5 の wrapperChecksum と一致しており、gradle/actions/wrapper-validation は引き続き通ります。

対象外

cobj.exe の SBOM は含めていません。NuGet の Microsoft.Windows.CppWinRT はビルド時のヘッダのみで、実行時依存は libm・libintl と同梱の lib/getopt.c 程度であり、自動生成できる依存メタデータが存在しないためです。必要であれば別途対応します。

確認したこと

  • フォーク (Attach a CycloneDX SBOM of libcobj.jar to every release yutaro-sakamoto/opensourcecobol4j#32) で同一内容の CI が全ジョブ成功
  • 本ブランチ (develop ベース) でローカルに cyclonedxDirectBomspotlessCheck が成功し、JSON / XML の両ファイルが生成されることを確認 (specVersion 1.6)
  • Gradle 更新に伴い JaCoCo の既定バージョンが 0.8.9 から 0.8.13 に変わりますが、jacocoTestCoverageVerification はフォークの CI で成功しています

Summary

Attach a CycloneDX 1.6 SBOM of libcobj.jar to every release, in two formats: libcobj-sbom.json and libcobj-sbom.xml. It is generated with the latest CycloneDX Gradle plugin, 3.4.1.

libcobj.jar is a shadow (fat) jar, so the third-party libraries it bundles cannot be identified from the jar itself. The SBOM lets users feed them to vulnerability scanners such as Trivy, Grype or Dependency-Track.

It lists every runtime dependency including transitive ones, with hashes and license information. includeConfigs is restricted to runtimeClasspath, so test-only dependencies such as JUnit and Testcontainers are excluded.

No third-party GitHub Actions were added

The SBOM is produced by the CycloneDX Gradle plugin rather than an external action such as anchore/sbom-action. The only actions involved are actions/upload-artifact and actions/download-artifact, both first-party and both already in use.

Where the SBOM is generated

In the same windows-build job that produces libcobj.jar, so the two always describe each other.

The generation step is deliberately not guarded by if: ${{inputs.upload-artifacts}}. Running it on every push and pull request is what keeps a broken SBOM configuration from surfacing only once a tag is pushed.

The Gradle wrapper moves from 8.2.1 to 8.14.5

This is the only incidental change in this PR, and it was required, for two reasons.

  1. The CycloneDX Gradle plugin 3.x requires Gradle 8.4 or newer.
  2. The ASM bundled with Gradle 8.2.1 cannot read Java 21 class files (major version 65), so the build fails during the configuration phase while instrumenting its own buildscript classpath, where any recent CycloneDX plugin pulls in a multi-release jackson-core jar.

Pinning the plugin to an old version (1.8.x, from 2023) avoids this, but the next Dependabot bump would break the build immediately. Gradle 8.2.1 also predates official Java 21 support, which CI has been using for a while.

The changes to gradlew, gradlew.bat and gradle-wrapper.jar are the standard output regenerated by ./gradlew wrapper. The SHA-256 of the wrapper jar matches the official wrapperChecksum published by Gradle for 8.14.5, so gradle/actions/wrapper-validation still passes.

Out of scope

No SBOM is produced for cobj.exe. The NuGet Microsoft.Windows.CppWinRT package provides build-time headers only, and the runtime dependencies amount to libm, libintl and the vendored lib/getopt.c, so there is no dependency metadata to generate from. This can be handled separately if wanted.

Verification

* Attach a CycloneDX SBOM of libcobj.jar to every release

libcobj.jar is a shadow jar, so the third-party libraries it bundles cannot
be identified from the jar itself. Generate a CycloneDX 1.6 SBOM with the
CycloneDX Gradle plugin and upload it as a release asset next to the jar.

The SBOM is produced by the same Windows build job that produces the released
libcobj.jar, so the two always describe each other, and it is generated on
every push and pull request as well - not only at release time - so a broken
SBOM configuration cannot go unnoticed until a tag is pushed.

Only actions/upload-artifact and actions/download-artifact are involved, both
of which the workflow already used.

The Gradle wrapper moves from 8.2.1 to 8.14.5. The ASM bundled with 8.2.1
cannot read the Java 21 class files in the multi-release jars that any
recent CycloneDX plugin pulls in, so the build fails while instrumenting its
own buildscript classpath. 8.2.1 also predates official Java 21 support,
which CI has been using for a while.

The release publishing job now runs on Java 21 like every other Gradle job.
The published bytecode is unchanged because the build targets Java 8.

* Address review feedback on the SBOM change

- Keep the release publishing job on Java 11. The CycloneDX plugin and its
  dependencies are Java 8 bytecode, the AlmaLinux 9 build job already runs
  Gradle on Java 11, and the JDK bump was unrelated to attaching an SBOM.
- Say why the SBOM generation step is not guarded by upload-artifacts.
- Match the Japanese README to the polite style used throughout the file.

* Publish the SBOM in both JSON and XML formats and update the CycloneDX plugin

- Bump org.cyclonedx.bom from 3.3.0 to 3.4.1
- Upload libcobj-sbom.xml as a release asset alongside libcobj-sbom.json
- Update both READMEs accordingly

* Clarify SBOM comments and use cwd-relative output paths in the READMEs
@yutaro-sakamoto
yutaro-sakamoto marked this pull request as ready for review August 19, 2026 14:54
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