Skip to content

ci: add SBOM generation to Docker and CLI releases#580

Merged
Aureliolo merged 1 commit intomainfrom
ci/sbom-release-assets
Mar 19, 2026
Merged

ci: add SBOM generation to Docker and CLI releases#580
Aureliolo merged 1 commit intomainfrom
ci/sbom-release-assets

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • Generate CycloneDX JSON SBOMs for all released artifacts using Syft
  • Container images: anchore/sbom-action scans each pushed image (backend, web, sandbox), SBOMs uploaded as release assets via update-release job
  • CLI binaries: GoReleaser sboms: stanza generates per-archive SBOMs (6 total), uploaded alongside checksums and binaries
  • Finalize-release extracts SBOM data from HTML comments and renders a "Software Bill of Materials (SBOM)" subsection in the Verification section
  • LICENSE now included in CLI binary archives (GoReleaser files: stanza)
  • Documentation updated: docs/security.md, CLAUDE.md, docs/architecture/tech-stack.md
  • anchore/sbom-action@* added to GitHub Actions allowlist

Satisfies OpenSSF Best Practices badge criterion QA-02.02 (SBOM with releases).

Test plan

  • Verify CI passes (workflow syntax validation)
  • On next v* tag release, verify:
    • 3 container SBOMs (sbom-backend.cdx.json, sbom-web.cdx.json, sbom-sandbox.cdx.json) attached to release
    • 6 CLI SBOMs (synthorg_{os}_{arch}.{tar.gz,zip}.cdx.json) attached to release
    • ## Verification section includes SBOM download links
    • SBOMs are valid CycloneDX JSON
  • Verify LICENSE is included in CLI binary archives
  • Re-verify QA-02.02 on OpenSSF badge form

Review coverage

Pre-reviewed by 2 agents (docs-consistency, infra-reviewer). 5 findings addressed (all documentation drift fixes). Infra review passed clean -- no security or correctness issues found.

🤖 Generated with Claude Code

Generate CycloneDX JSON SBOMs for all released artifacts using Syft:
- Container images: anchore/sbom-action scans each pushed image, SBOMs
  uploaded as release assets via update-release job
- CLI binaries: GoReleaser sboms: stanza generates per-archive SBOMs
- Finalize-release extracts SBOM data and renders download links in
  the Verification section
- LICENSE now included in CLI binary archives
- docs/security.md documents the new SBOM subsection
- CLAUDE.md and tech-stack.md updated to reflect SBOM generation

Satisfies OpenSSF Best Practices badge criterion QA-02.02.

Pre-reviewed by 2 agents, 5 findings addressed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/download-artifact 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c 🟢 6.1
Details
CheckScoreReason
Maintained🟢 1025 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 10all changesets reviewed
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 10SAST tool is run on all commits
actions/anchore/sbom-action 57aae528053a48a3f6235f2d9461b05fbcb7366d 🟢 7.9
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained🟢 1030 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 9binaries present in source code
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Pinned-Dependencies🟢 7dependency not pinned by hash detected -- score normalized to 7
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Security-Policy🟢 10security policy file detected
Signed-Releases⚠️ -1no releases found
Packaging🟢 10packaging workflow detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0

Scanned Files

  • .github/workflows/docker.yml

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the project's supply chain security posture by integrating comprehensive Software Bill of Materials (SBOM) generation into the release process for both Docker container images and CLI binaries. These changes ensure that all released artifacts are accompanied by detailed CycloneDX JSON SBOMs, improving transparency and compliance with security best practices.

Highlights

  • SBOM Generation: Implemented CycloneDX JSON SBOM generation for all released artifacts using Syft.
  • Container Image SBOMs: Enabled anchore/sbom-action to scan container images (backend, web, sandbox) and upload SBOMs as release assets.
  • CLI Binary SBOMs: Configured GoReleaser to generate per-archive SBOMs for CLI binaries, which are then uploaded alongside other release assets.
  • Release Notes Integration: Enhanced the finalize-release workflow to extract and display SBOM data in the release notes' Verification section.
  • License Inclusion: Included the LICENSE file within CLI binary archives.
  • Documentation Updates: Updated relevant documentation files (docs/security.md, CLAUDE.md, docs/architecture/tech-stack.md) to reflect these changes.
  • GitHub Actions Allowlist: Added anchore/sbom-action@* to the GitHub Actions allowlist.
  • OpenSSF Best Practices: Satisfied OpenSSF Best Practices badge criterion QA-02.02 for SBOM with releases.
Ignored Files
  • Ignored by pattern: .github/workflows/** (3)
    • .github/workflows/cli.yml
    • .github/workflows/docker.yml
    • .github/workflows/finalize-release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f93fdb8f-c860-4c30-8719-1912b15c5d7d

📥 Commits

Reviewing files that changed from the base of the PR and between a1bedb8 and 8419aa7.

📒 Files selected for processing (7)
  • .github/workflows/cli.yml
  • .github/workflows/docker.yml
  • .github/workflows/finalize-release.yml
  • CLAUDE.md
  • cli/.goreleaser.yml
  • docs/architecture/tech-stack.md
  • docs/security.md
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: CLI Test (windows-latest)
  • GitHub Check: Build Backend
🧰 Additional context used
📓 Path-based instructions (1)
docs/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Always read the relevant docs/design/ page before implementing any feature or planning any issue. The design spec is the starting point for architecture, data models, and behavior.

Files:

  • docs/security.md
  • docs/architecture/tech-stack.md
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Docker workflow (`.github/workflows/docker.yml`) builds backend + web + sandbox images, pushes to GHCR, signs with cosign, performs Trivy/Grype scans (CRITICAL = hard fail, HIGH = warn-only), and generates SLSA L3 provenance attestations. Images only pushed after scans pass.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: CLI workflow (`.github/workflows/cli.yml`) runs Go lint (golangci-lint + go vet) + test (race, coverage) + build (cross-compile matrix) + vulnerability check (govulncheck) + fuzz testing. Cross-compiles for linux/darwin/windows × amd64/arm64. GoReleaser release on v* tags with cosign keyless signing and SLSA L3 attestations.
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to .github/workflows/docker.yml : CI Docker: build → scan → push to GHCR + cosign sign + SLSA L3 provenance via attest-build-provenance (images only pushed after Trivy/Grype scans pass).
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Finalize Release workflow (`.github/workflows/finalize-release.yml`) publishes draft releases created by Release Please. Triggers on workflow_run completion of Docker and CLI workflows. Extracts CLI checksums, cosign verification, and container verification data from HTML comments; assembles into combined Verification section in release notes.
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Finalize Release workflow (`.github/workflows/finalize-release.yml`) publishes draft releases created by Release Please. Triggers on workflow_run completion of Docker and CLI workflows. Extracts CLI checksums, cosign verification, and container verification data from HTML comments; assembles into combined Verification section in release notes.

Applied to files:

  • .github/workflows/finalize-release.yml
  • CLAUDE.md
  • .github/workflows/cli.yml
  • .github/workflows/docker.yml
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: CLI workflow (`.github/workflows/cli.yml`) runs Go lint (golangci-lint + go vet) + test (race, coverage) + build (cross-compile matrix) + vulnerability check (govulncheck) + fuzz testing. Cross-compiles for linux/darwin/windows × amd64/arm64. GoReleaser release on v* tags with cosign keyless signing and SLSA L3 attestations.

Applied to files:

  • .github/workflows/finalize-release.yml
  • CLAUDE.md
  • cli/.goreleaser.yml
  • .github/workflows/cli.yml
  • docs/security.md
  • .github/workflows/docker.yml
  • docs/architecture/tech-stack.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Release workflow (`.github/workflows/release.yml`) uses Release Please to auto-create release PRs. Ensures manifest version's git tag exists. Uses RELEASE_PLEASE_TOKEN secret so tag creation triggers downstream workflows. Merging release PR creates draft GitHub Release with changelog.

Applied to files:

  • .github/workflows/finalize-release.yml
  • CLAUDE.md
  • .github/workflows/cli.yml
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Docker workflow (`.github/workflows/docker.yml`) builds backend + web + sandbox images, pushes to GHCR, signs with cosign, performs Trivy/Grype scans (CRITICAL = hard fail, HIGH = warn-only), and generates SLSA L3 provenance attestations. Images only pushed after scans pass.

Applied to files:

  • .github/workflows/finalize-release.yml
  • CLAUDE.md
  • .github/workflows/cli.yml
  • docs/security.md
  • .github/workflows/docker.yml
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to .github/workflows/docker.yml : CI Docker: build → scan → push to GHCR + cosign sign + SLSA L3 provenance via attest-build-provenance (images only pushed after Trivy/Grype scans pass).

Applied to files:

  • .github/workflows/finalize-release.yml
  • CLAUDE.md
  • .github/workflows/cli.yml
  • docs/security.md
  • .github/workflows/docker.yml
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to docker/{Dockerfile*,compose.yml} : Docker: Backend uses 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web uses nginxinc/nginx-unprivileged, Vue 3 SPA with PrimeVue + Tailwind CSS, SPA routing, API/WebSocket proxy to backend.

Applied to files:

  • CLAUDE.md
  • docs/security.md
  • .github/workflows/docker.yml
  • docs/architecture/tech-stack.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Applies to Dockerfile : Backend: 3-stage build (builder → setup → distroless runtime), Chainguard Python, non-root (UID 65532), CIS-hardened. Web: nginxinc/nginx-unprivileged, Vue 3 SPA, SPA routing, API/WebSocket proxy. Sandbox: Python 3.14 + Node.js + git, non-root (UID 10001).

Applied to files:

  • CLAUDE.md
  • docs/security.md
  • .github/workflows/docker.yml
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to docker/** : Docker build context: single root .dockerignore (both images build with context: .). Tags: CI tags images with version from pyproject.toml ([tool.commitizen].version), semver, and SHA.

Applied to files:

  • CLAUDE.md
  • docs/security.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Applies to package.json : Maintain Node.js 20+ requirement. Configure Vue 3 build with TypeScript, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus. Set up testing with Vitest + fast-check, linting with ESLint, and type checking with vue-tsc.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Applies to docker/compose.yml : Configure Docker Compose with backend, web, and sandbox services. All environment variables defined in `docker/.env` (generate from `docker/.env.example`).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Pre-commit hooks: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint (Dockerfile linting).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Pre-push hooks: mypy type-check + pytest unit tests + golangci-lint + go vet + go test (CLI, conditional on cli/**/*.go) (fast gate before push, skipped in pre-commit.ci — dedicated CI jobs already run these).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Pages workflow (`.github/workflows/pages.yml`) exports OpenAPI schema via `scripts/export_openapi.py`, builds Astro landing + Zensical docs, copies CLI install scripts to `/get/`, merges, and deploys to GitHub Pages on push to main.

Applied to files:

  • CLAUDE.md
  • cli/.goreleaser.yml
  • .github/workflows/docker.yml
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to .github/workflows/**/*.yml : Path filtering: dorny/paths-filter detects Python/dashboard/docker changes; jobs only run when their domain is affected. CLI has its own workflow (cli.yml).

Applied to files:

  • CLAUDE.md
  • .github/workflows/cli.yml
  • .github/workflows/docker.yml
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Dependabot: auto-updates Docker image digests and versions daily.

Applied to files:

  • CLAUDE.md
  • docs/security.md
  • .github/workflows/docker.yml
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: PR Preview workflow (`.github/workflows/pages-preview.yml`) builds site on PRs and workflow_dispatch. Injects 'Development Preview' banner and deploys to Cloudflare Pages. Each PR gets unique preview URL at `pr-<number>.synthorg-pr-preview.pages.dev`. Cleanup job deletes preview on PR close.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Applies to .pre-commit-config.yaml : Configure hooks: trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-json, check-merge-conflict, check-added-large-files, no-commit-to-branch (main), ruff check+format, gitleaks, hadolint. Pre-push hooks: mypy + pytest unit + golangci-lint + go vet + go test (conditional on cli changes).

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Applies to go.mod : Maintain Go 1.26+ requirement. Dependencies: Cobra (CLI framework), charmbracelet/huh and charmbracelet/lipgloss (UI), sigstore-go (code signing), go-containerregistry (container image verification), go-tuf (TUF client for Sigstore).

Applied to files:

  • cli/.goreleaser.yml
  • docs/architecture/tech-stack.md
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to cli/** : CLI: Go 1.26+, dependencies in cli/go.mod (Cobra, charmbracelet/huh).

Applied to files:

  • cli/.goreleaser.yml
  • .github/workflows/cli.yml
📚 Learning: 2026-03-19T09:01:47.243Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-19T09:01:47.243Z
Learning: Path filtering uses `dorny/paths-filter` to detect Python/dashboard/docker changes; jobs only run when their domain is affected. CLI has its own workflow (cli.yml).

Applied to files:

  • .github/workflows/cli.yml
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Commits: <type>: <description> — types: feat, fix, refactor, docs, test, chore, perf, ci. Enforced by commitizen (commit-msg hook). Signed commits: required on main via branch protection — all commits must be GPG/SSH signed.

Applied to files:

  • docs/security.md
🪛 LanguageTool
CLAUDE.md

[uncategorized] ~107-~107: The official name of this software platform is spelled with a capital “H”.
Context: ...iles, compose, .env.example - CI: .github/workflows/docker.yml -- build -> scan ...

(GITHUB)

docs/security.md

[style] ~175-~175: A comma is missing here.
Context: ... - CLI binaries: per-archive SBOMs (e.g. synthorg_linux_amd64.tar.gz.cdx.json)...

(EG_NO_COMMA)

🔇 Additional comments (22)
.github/workflows/cli.yml (3)

265-266: LGTM! Syft installation is properly SHA-pinned.

The action is pinned by full commit hash, consistent with the project's supply chain security practices.


313-313: LGTM! SBOM artifacts included in release upload.

The glob pattern cli/dist/*.cdx.json correctly captures the per-archive CycloneDX SBOMs generated by GoReleaser's sboms: stanza.


428-436: LGTM! SBOM metadata embedded for finalize-release extraction.

The HTML comment block follows the established pattern (CLI_VERIFICATION_DATA, CLI_COSIGN_DATA) and lists all 6 expected SBOM artifacts matching the cross-compile matrix.

docs/architecture/tech-stack.md (2)

65-65: LGTM! CLI documentation updated with SBOM details.

The documentation accurately reflects the GoReleaser sboms: stanza configuration and CycloneDX JSON output format.


82-82: LGTM! Container packaging documentation updated with SBOM details.

The documentation correctly describes the anchore/sbom-action usage for per-image CycloneDX JSON SBOM generation.

cli/.goreleaser.yml (2)

33-37: LGTM! LICENSE included in release archives.

Using mtime: "{{ .CommitDate }}" ensures reproducible builds by setting consistent timestamps.


43-48: LGTM! SBOM generation via GoReleaser.

The sboms: stanza correctly configures Syft to generate CycloneDX JSON SBOMs for each archive artifact. The output naming pattern {{ .ArtifactName }}.cdx.json matches the filenames listed in the CLI workflow's SBOM data block.

.github/workflows/docker.yml (6)

227-241: LGTM! Backend SBOM generation properly configured.

The SBOM is generated from the pushed image digest (ensuring it matches the signed/attested image), uses CycloneDX JSON format, and is uploaded as an artifact for the update-release job.


410-424: LGTM! Web SBOM generation follows the same pattern.


593-607: LGTM! Sandbox SBOM generation follows the same pattern.


618-623: LGTM! Artifact download correctly aggregates SBOMs.

The pattern: sbom-* matches the uploaded artifact names (sbom-backend, sbom-web, sbom-sandbox), and merge-multiple: true flattens them into the sboms/ directory.


696-701: LGTM! Container SBOM metadata embedded for finalize-release extraction.

The HTML comment block follows the established pattern and lists the three expected container SBOM artifacts.


711-716: LGTM! Defensive upload with warning on missing files.

The ls check before gh release upload prevents silent failures and provides a clear warning if SBOMs are unexpectedly missing.

.github/workflows/finalize-release.yml (4)

125-141: LGTM! SBOM data extraction follows established patterns.

The extraction logic mirrors the existing verification data extraction (CLI_VERIFICATION_DATA, CONTAINER_VERIFICATION_DATA), with appropriate warnings when markers are present but content is empty.


169-169: LGTM! Guard condition extended for SBOM content.

The Verification section is now assembled when any verification or SBOM data is present.


208-222: LGTM! SBOM subsection rendering is well-structured.

The conditional logic correctly handles CLI-only, container-only, or both SBOM sources, with clear labeling under a single "Software Bill of Materials (SBOM)" heading.


233-235: LGTM! SBOM markers cleaned up after extraction.

Both CLI_SBOM_DATA and CONTAINER_SBOM_DATA HTML comments are removed from the final release body, consistent with other verification data markers.

CLAUDE.md (3)

107-107: LGTM! Docker CI documentation updated with SBOM details.

The description accurately reflects the Syft CycloneDX JSON SBOM generation and attachment to releases.


275-275: LGTM! CLI workflow documentation updated with SBOM details.

The description accurately documents the GoReleaser sboms: stanza for per-archive SBOM generation and the release notes SBOM file listings.


289-289: LGTM! Finalize Release documentation updated with SBOM extraction.

The description correctly reflects that SBOM data is extracted from HTML comments and rendered in the combined Verification section.

docs/security.md (2)

125-126: LGTM! Clarified distinction between Buildx and Syft SBOMs.

The updated text correctly distinguishes between:

  • Buildx SPDX SBOMs (registry attestations, SLSA L1)
  • Syft CycloneDX JSON SBOMs (release assets, detailed below)

This avoids confusion about the two complementary SBOM mechanisms.


166-178: LGTM! Comprehensive SBOM documentation section.

The new section clearly documents:

  • Container image SBOMs with specific filenames
  • CLI binary SBOMs with naming pattern
  • Registry attestations for completeness

This provides users with all the information needed to locate and verify SBOMs.


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Software Bill of Materials (SBOM) artifacts now generated and included with all CLI binary and container image releases.
    • Release notes enhanced with dedicated SBOM documentation section.
  • Documentation

    • Updated security documentation with comprehensive SBOM details and availability information.
    • Updated architecture documentation to reflect SBOM generation tooling.

Walkthrough

This change adds Software Bill of Materials (SBOM) generation across the CI/CD pipeline for both CLI and container releases. SBOMs are generated using Syft and included as CycloneDX JSON artifacts, with metadata embedded in release notes through HTML comments and extracted during finalization.

Changes

Cohort / File(s) Summary
CLI Release Workflow
.github/workflows/cli.yml
Added Syft installation, SBOM artifact upload (.cdx.json), and HTML comment metadata in release notes containing SBOM filenames for all binary builds.
Docker Release Workflow
.github/workflows/docker.yml
Added SBOM generation for backend, web, and sandbox images via anchore/sbom-action, uploaded as artifacts with 30-day retention, and added extraction logic to include SBOMs in release upload during finalization.
Release Finalization
.github/workflows/finalize-release.yml
Added extraction of CLI_SBOM_DATA and CONTAINER_SBOM_DATA HTML comments from release body, with conditional construction of a new "Software Bill of Materials" verification subsection and cleanup of existing SBOM markers.
CLI Packaging Configuration
cli/.goreleaser.yml
Added LICENSE file inclusion in archives and configured GoReleaser to generate CycloneDX JSON SBOMs per archive via Syft.
Documentation
CLAUDE.md, docs/architecture/tech-stack.md, docs/security.md
Updated workflow descriptions and security documentation to reflect SBOM generation, attachment to releases, and registry attestations for both CLI and container images.

Sequence Diagram(s)

sequenceDiagram
    participant GHA as GitHub Actions
    participant Syft as Syft Tool
    participant GR as GoReleaser
    participant Artifacts as Artifact Storage
    participant Release as GitHub Release
    participant Finalize as Finalize Job

    GHA->>Syft: Install Syft binary
    
    rect rgba(100, 150, 200, 0.5)
    Note over GHA,GR: CLI Release Path
    GHA->>GR: Execute GoReleaser with sboms config
    GR->>Syft: Invoke for each archive
    Syft-->>GR: Generate .cdx.json per archive
    GR->>Artifacts: Upload .tar.gz/.zip + .cdx.json
    GHA->>Release: Create draft with CLI_SBOM_DATA metadata
    end

    rect rgba(150, 100, 200, 0.5)
    Note over GHA,Artifacts: Container Release Path
    GHA->>Syft: Run anchore/sbom-action per image
    Syft-->>Artifacts: Output sbom-*.cdx.json per image
    GHA->>Artifacts: Upload SBOM artifacts (30-day retention)
    GHA->>Release: Create draft with CONTAINER_SBOM_DATA metadata
    end

    rect rgba(200, 150, 100, 0.5)
    Note over Finalize,Release: Finalize Phase
    Finalize->>Release: Extract CLI_SBOM_DATA and CONTAINER_SBOM_DATA
    Finalize->>Artifacts: Download all sbom-*.cdx.json files
    Finalize->>Release: Upload downloaded SBOMs to release
    Finalize->>Release: Build combined Verification section with SBOM subsection
    Finalize->>Release: Publish finalized release with all SBOMs
    end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding SBOM generation to Docker and CLI releases, which is directly supported by all the file changes.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing SBOM generation for container images and CLI binaries, documentation updates, and OpenSSF compliance goals.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/sbom-release-assets
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch ci/sbom-release-assets
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 19, 2026 10:43 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces SBOM generation for Docker images and CLI binaries using Syft, a significant step in enhancing supply chain security. The changes include updating the GoReleaser configuration to automate SBOM creation for CLI archives and to bundle the LICENSE file within them. Correspondingly, the documentation across CLAUDE.md, docs/architecture/tech-stack.md, and docs/security.md has been updated to reflect these new capabilities. The implementation in .goreleaser.yml appears correct. My review focuses on minor stylistic inconsistencies in the documentation to ensure consistency and readability.

- **Sandbox**: `synthorg-sandbox` — Python 3.14 + Node.js + git, non-root (UID 10001), agent code execution sandbox
- **Config**: all Docker files in `docker/` — Dockerfiles, compose, `.env.example`
- **CI**: `.github/workflows/docker.yml` build scan push to GHCR + cosign sign + SLSA L3 provenance via `attest-build-provenance` (images only pushed after Trivy/Grype scans pass)
- **CI**: `.github/workflows/docker.yml` -- build -> scan -> push to GHCR + cosign sign + SLSA L3 provenance via `attest-build-provenance` + Syft SBOM generation (CycloneDX JSON, one per image) attached to releases (images only pushed after Trivy/Grype scans pass)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For stylistic consistency with other list items in this file that use an em-dash (), please replace the two hyphens (--) with an em-dash.

Suggested change
- **CI**: `.github/workflows/docker.yml` -- build -> scan -> push to GHCR + cosign sign + SLSA L3 provenance via `attest-build-provenance` + Syft SBOM generation (CycloneDX JSON, one per image) attached to releases (images only pushed after Trivy/Grype scans pass)
- **CI**: `.github/workflows/docker.yml` build -> scan -> push to GHCR + cosign sign + SLSA L3 provenance via `attest-build-provenance` + Syft SBOM generation (CycloneDX JSON, one per image) attached to releases (images only pushed after Trivy/Grype scans pass)

- **Docker**: `.github/workflows/docker.yml` — builds backend + web + sandbox images, pushes to GHCR, signs with cosign. SLSA L3 provenance attestations via `actions/attest-build-provenance` (SHA-pinned, Sigstore-signed, pushed to registry). Scans: Trivy (CRITICAL = hard fail, HIGH = warn-only) + Grype (critical cutoff) + CIS Docker Benchmark v1.6.0 compliance (informational). CVE triage via `.github/.trivyignore.yaml` and `.github/.grype.yaml`. Images only pushed after scans pass. Triggers on push to main and version tags (`v*`).
- **Matrix**: Python 3.14
- **CLI**: `.github/workflows/cli.yml` — Go lint (`golangci-lint` + `go vet`) + test (`-race -coverprofile`) + build (cross-compile matrix: linux/darwin/windows × amd64/arm64) + vulnerability check (`govulncheck`) + fuzz testing (main-only, 30s/target, `continue-on-error`, matrix over 5 packages) on `cli/**` changes. `cli-pass` gate includes fuzz result as informational warning. GoReleaser release on `v*` tags (attaches assets to the draft Release Please release). Cosign keyless signing of `checksums.txt` (`.sig` + `.pem` attached to release). SLSA L3 provenance attestations via `actions/attest-build-provenance` (SHA-pinned, Sigstore-signed) for individual binaries and checksums file. Sigstore provenance bundle (`.sigstore.json`) attached to release for OpenSSF Scorecard signed-releases scoring. Post-release step appends install instructions + checksum table + cosign verification + provenance verification instructions to the draft release notes (while still in draft — before finalize-release publishes).
- **CLI**: `.github/workflows/cli.yml` — Go lint (`golangci-lint` + `go vet`) + test (`-race -coverprofile`) + build (cross-compile matrix: linux/darwin/windows × amd64/arm64) + vulnerability check (`govulncheck`) + fuzz testing (main-only, 30s/target, `continue-on-error`, matrix over 5 packages) on `cli/**` changes. `cli-pass` gate includes fuzz result as informational warning. GoReleaser release on `v*` tags (attaches assets to the draft Release Please release). Syft SBOM generation per binary archive (CycloneDX JSON, via GoReleaser `sboms:` stanza). Cosign keyless signing of `checksums.txt` (`.sig` + `.pem` attached to release). SLSA L3 provenance attestations via `actions/attest-build-provenance` (SHA-pinned, Sigstore-signed) for individual binaries and checksums file. Sigstore provenance bundle (`.sigstore.json`) attached to release for OpenSSF Scorecard signed-releases scoring. Post-release step appends install instructions + checksum table + cosign verification + provenance verification + SBOM file listings to the draft release notes (while still in draft -- before finalize-release publishes).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For stylistic consistency, please use an em-dash () here instead of two hyphens (--).

Suggested change
- **CLI**: `.github/workflows/cli.yml` — Go lint (`golangci-lint` + `go vet`) + test (`-race -coverprofile`) + build (cross-compile matrix: linux/darwin/windows × amd64/arm64) + vulnerability check (`govulncheck`) + fuzz testing (main-only, 30s/target, `continue-on-error`, matrix over 5 packages) on `cli/**` changes. `cli-pass` gate includes fuzz result as informational warning. GoReleaser release on `v*` tags (attaches assets to the draft Release Please release). Syft SBOM generation per binary archive (CycloneDX JSON, via GoReleaser `sboms:` stanza). Cosign keyless signing of `checksums.txt` (`.sig` + `.pem` attached to release). SLSA L3 provenance attestations via `actions/attest-build-provenance` (SHA-pinned, Sigstore-signed) for individual binaries and checksums file. Sigstore provenance bundle (`.sigstore.json`) attached to release for OpenSSF Scorecard signed-releases scoring. Post-release step appends install instructions + checksum table + cosign verification + provenance verification + SBOM file listings to the draft release notes (while still in draft -- before finalize-release publishes).
- **CLI**: `.github/workflows/cli.yml` — Go lint (`golangci-lint` + `go vet`) + test (`-race -coverprofile`) + build (cross-compile matrix: linux/darwin/windows × amd64/arm64) + vulnerability check (`govulncheck`) + fuzz testing (main-only, 30s/target, `continue-on-error`, matrix over 5 packages) on `cli/**` changes. `cli-pass` gate includes fuzz result as informational warning. GoReleaser release on `v*` tags (attaches assets to the draft Release Please release). Syft SBOM generation per binary archive (CycloneDX JSON, via GoReleaser `sboms:` stanza). Cosign keyless signing of `checksums.txt` (`.sig` + `.pem` attached to release). SLSA L3 provenance attestations via `actions/attest-build-provenance` (SHA-pinned, Sigstore-signed) for individual binaries and checksums file. Sigstore provenance bundle (`.sigstore.json`) attached to release for OpenSSF Scorecard signed-releases scoring. Post-release step appends install instructions + checksum table + cosign verification + provenance verification + SBOM file listings to the draft release notes (while still in draft — before finalize-release publishes).

- **Dependabot** auto-updates digests daily for all three Dockerfiles
- **cosign keyless signing** on every pushed image (Sigstore OIDC-bound)
- **SBOM and build-level provenance** (SLSA L1) auto-generated by Docker Buildx
- **Buildx SPDX SBOMs** (SLSA L1) auto-generated and pushed to GHCR as registry attestations (inspect via `docker buildx imagetools inspect`). Standalone CycloneDX JSON SBOMs are generated separately by Syft -- see [Software Bill of Materials](#software-bill-of-materials-sbom) below.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For stylistic consistency with other prose in this document, please use an em-dash () for separation instead of two hyphens (--).

Suggested change
- **Buildx SPDX SBOMs** (SLSA L1) auto-generated and pushed to GHCR as registry attestations (inspect via `docker buildx imagetools inspect`). Standalone CycloneDX JSON SBOMs are generated separately by Syft -- see [Software Bill of Materials](#software-bill-of-materials-sbom) below.
- **Buildx SPDX SBOMs** (SLSA L1) auto-generated and pushed to GHCR as registry attestations (inspect via `docker buildx imagetools inspect`). Standalone CycloneDX JSON SBOMs are generated separately by Syft see [Software Bill of Materials](#software-bill-of-materials-sbom) below.

- **Git commits**: GPG/SSH signed (enforced by branch protection ruleset)
- **GitHub Actions**: All actions pinned by full SHA commit hash
- **GitHub Releases**: Immutable releases enabled — once published, assets and body cannot be modified (prevents supply chain tampering). Releases are created as drafts by Release Please, finalized after all assets are attached.
- **GitHub Releases**: Immutable releases enabled -- once published, assets and body cannot be modified (prevents supply chain tampering). Releases are created as drafts by Release Please, finalized after all assets are attached.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This change introduces a stylistic inconsistency. The original line used an em-dash (), which is consistent with other prose in the document. Please revert the change from two hyphens (--) back to an em-dash.

Suggested change
- **GitHub Releases**: Immutable releases enabled -- once published, assets and body cannot be modified (prevents supply chain tampering). Releases are created as drafts by Release Please, finalized after all assets are attached.
- **GitHub Releases**: Immutable releases enabled once published, assets and body cannot be modified (prevents supply chain tampering). Releases are created as drafts by Release Please, finalized after all assets are attached.

@Aureliolo Aureliolo merged commit db459cf into main Mar 19, 2026
47 checks passed
@Aureliolo Aureliolo deleted the ci/sbom-release-assets branch March 19, 2026 11:12
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 19, 2026 11:12 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 19, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.3.7](v0.3.6...v0.3.7)
(2026-03-19)


### Features

* **engine:** implement Hybrid Plan + ReAct execution loop
([#582](#582))
([008147c](008147c))
* implement first-run setup wizard
([#584](#584))
([dfed931](dfed931))


### Bug Fixes

* **api:** address ZAP DAST scan findings
([#579](#579))
([ce9a3e0](ce9a3e0))
* **cli:** regenerate compose and re-exec binary on update
([#576](#576))
([3f226eb](3f226eb))


### CI/CD

* add SBOM generation to Docker and CLI releases
([#580](#580))
([db459cf](db459cf))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Aureliolo added a commit that referenced this pull request Mar 19, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.3.7](v0.3.6...v0.3.7)
(2026-03-19)


### Features

* **engine:** implement Hybrid Plan + ReAct execution loop
([#582](#582))
([008147c](008147c))
* implement first-run setup wizard
([#584](#584))
([dfed931](dfed931))


### Bug Fixes

* **api:** address ZAP DAST scan findings
([#579](#579))
([ce9a3e0](ce9a3e0))
* **cli:** auto-delete binary on Windows, prune images, fix GoReleaser
([#590](#590))
([eb7c691](eb7c691))
* **cli:** regenerate compose and re-exec binary on update
([#576](#576))
([3f226eb](3f226eb))


### CI/CD

* add SBOM generation to Docker and CLI releases
([#580](#580))
([db459cf](db459cf))


### Maintenance

* **main:** release 0.3.7
([#583](#583))
([bf58779](bf58779))
* reset failed v0.3.7 release
([#591](#591))
([b69000d](b69000d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added engine Hybrid Plan + ReAct execution loop
  * Added first-run setup wizard

* **Bug Fixes**
  * Addressed ZAP DAST scan issues
  * Fixed CLI Windows/image/update issues

* **Maintenance**
  * Added SBOM generation for Docker/CLI releases
  * General maintenance updates

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Aureliolo added a commit that referenced this pull request Mar 19, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.3.7](v0.3.6...v0.3.7)
(2026-03-19)


### Features

* **engine:** implement Hybrid Plan + ReAct execution loop
([#582](#582))
([008147c](008147c))
* implement first-run setup wizard
([#584](#584))
([dfed931](dfed931))


### Bug Fixes

* **api:** address ZAP DAST scan findings
([#579](#579))
([ce9a3e0](ce9a3e0))
* **ci:** reset failed v0.3.7 release and fix syft SBOM scan
([#593](#593))
([d1508c2](d1508c2))
* **cli:** auto-delete binary on Windows, prune images, fix GoReleaser
([#590](#590))
([eb7c691](eb7c691))
* **cli:** regenerate compose and re-exec binary on update
([#576](#576))
([3f226eb](3f226eb))


### CI/CD

* add SBOM generation to Docker and CLI releases
([#580](#580))
([db459cf](db459cf))


---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Aureliolo added a commit that referenced this pull request Mar 19, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.3.7](v0.3.6...v0.3.7)
(2026-03-19)


### Features

* **engine:** implement Hybrid Plan + ReAct execution loop
([#582](#582))
([008147c](008147c))
* implement first-run setup wizard
([#584](#584))
([dfed931](dfed931))


### Bug Fixes

* **api:** address ZAP DAST scan findings
([#579](#579))
([ce9a3e0](ce9a3e0))
* **ci:** remove CLI SBOM generation, reset failed v0.3.7
([#595](#595))
([d0f4992](d0f4992))
* **ci:** reset failed v0.3.7 release and fix syft SBOM scan
([#593](#593))
([d1508c2](d1508c2))
* **cli:** auto-delete binary on Windows, prune images, fix GoReleaser
([#590](#590))
([eb7c691](eb7c691))
* **cli:** regenerate compose and re-exec binary on update
([#576](#576))
([3f226eb](3f226eb))


### CI/CD

* add SBOM generation to Docker and CLI releases
([#580](#580))
([db459cf](db459cf))




---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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