SBOM
如何在 GitHub Actions 中產生 SBOM
從 GitHub Actions 管線取得 SBOM 的方式有四種,而它們描述的對象各不相同:儲存庫、磁碟上的檔案、其中任一者的簽章副本,或建置實際擷取的內容。請依您需要 SBOM 證明什麼來選擇。以下每種做法都附有執行所需的 YAML 或指令。
更新日期
四種做法
| 功能 | 做法 | SBOM 描述的內容 | 所需工夫 |
|---|---|---|---|
| 相依關係圖匯出 | GitHub 的相依關係圖 | 預設分支上儲存庫的 manifest 與 lockfile | 無 |
| 產生工具步驟 | Syft、Trivy、cdxgen | 步驟執行時眼前的檔案或映像檔 | 每個作業一個步驟 |
| 證明 | actions/attest | 您傳入的任何 SBOM,經簽章並綁定到建置產物 | 產生後再加一個步驟 |
| 建置時記錄 | CRACI | 作業執行期間擷取的內容,附完整性狀態 | 變更 runs-on |
1. 匯出相依關係圖
GitHub 會根據儲存庫中的 manifest 與鎖定檔(lockfile)建立相依關係圖,並可將其匯出為 SPDX SBOM。這不需要變更工作流程:開啟儲存庫的 Insights 分頁,選擇 Dependency graph,再點選 Export SBOM。它描述的是預設分支上的儲存庫,而不是特定的建置,因此工作流程安裝的工具與套件不會包含在內。
若要以腳本執行,請使用 REST API。GET /repos/{owner}/{repo}/dependency-graph/sbom 只需一次呼叫即可回傳 SPDX JSON,但 GitHub 將在 2026 年 11 月 13 日之後停用它。替代方式是非同步的:先請求一份報告,再擷取它回傳的 sbom_url。該 URL 在 SBOM 產生期間會回應 202,之後再重新導向到 SPDX JSON 檔案,GitHub 最多保留該檔案一週。
# Export the dependency graph as SPDX JSON (closing down after November 13, 2026)
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2026-03-10" \
https://api.github.com/repos/OWNER/REPO/dependency-graph/sbom
# The replacement: request a report; the response carries an sbom_url
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2026-03-10" \
https://api.github.com/repos/OWNER/REPO/dependency-graph/sbom/generate-report 2. 加入產生工具步驟
工作流程中的一個步驟會針對工作區或映像檔執行產生工具。anchore/sbom-action 會執行 Syft:預設會掃描工作區目錄並輸出 SPDX JSON,也可以改為掃描容器映像檔,並將 SBOM 上傳為工作流程建置產物,同時附加到版本發布中。它的 README 要求 contents: write,在將 SBOM 附加到版本發布時還需要 actions: read:
name: sbom
on:
push:
branches: [main]
release:
types: [published]
jobs:
sbom:
runs-on: ubuntu-latest
permissions:
contents: write # upload the SBOM
actions: read # attach it to a release
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
- run: npm ci
# Scan the workspace after the install step
- uses: anchore/sbom-action@v0
with:
path: .
format: cyclonedx-json format 可設為 spdx、spdx-json、cyclonedx 或 cyclonedx-json。若要掃描映像檔,請將 path 換成 image,例如 image: ghcr.io/OWNER/app:1.0。BuildKit 本身的映像檔 SBOM,請參閱 Docker SBOM。
Trivy 與 cdxgen 也能以相同方式、作為一般的 run 步驟執行。cdxgen 輸出 CycloneDX;自第 13 版起,其 npm 套件名稱為 @cdxgen/cdxgen:
steps:
- uses: actions/checkout@v7
- run: npm ci
- run: npm install -g @cdxgen/cdxgen --ignore-scripts
- run: cdxgen -o bom.json .
- uses: actions/upload-artifact@v7
with:
name: sbom
path: bom.json 時機很重要。請在相依套件安裝完成後再執行此步驟,否則它看不到這些套件。即使如此,產生工具也只看得到眼前的檔案:由腳本下載、使用後又刪除的套件,或在套件管理工具之外安裝的工具,都可能遺漏。
3. 以證明形式簽章
GitHub 的建置產物證明(artifact attestations)會將 SBOM 綁定到它所描述的建置產物,並以 Sigstore 簽章。actions/attest@v4 可透過 sbom-path 接受最大 16 MB 的 SPDX 或 CycloneDX JSON。若未指定 sbom-path,則會改為產生 SLSA 建置來源證明。actions/attest-sbom 即將被淘汰,由 actions/attest 取代,目前它已改為包裝 actions/attest。作業需要 id-token: write 以取得簽章憑證,並需要 attestations: write 以儲存結果:
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write # sign with a Sigstore certificate
contents: read
attestations: write # store the attestation
steps:
- uses: actions/checkout@v7
- run: make build # writes dist/my-app
- uses: anchore/sbom-action@v0
with:
path: .
format: spdx-json
output-file: sbom.spdx.json
upload-artifact: false
- uses: actions/attest@v4
with:
subject-path: dist/my-app
sbom-path: sbom.spdx.json 若為容器映像檔,請傳入 subject-name 與 subject-digest 以取代 subject-path,設定 push-to-registry: true,並加入 packages: write。建置產物證明可用於目前所有 GitHub 方案的公開儲存庫;私有與內部儲存庫則需要 GitHub Enterprise Cloud。
接著,GitHub CLI 會檢查 SBOM 由誰產生、對應哪個建置產物。SBOM 證明需要 --predicate-type;加上 --format json 即可查看 SBOM 本身。若為映像檔,請以 oci:// 加上映像檔名稱取代檔案路徑。
gh attestation verify dist/my-app \
-R OWNER/REPO \
--predicate-type https://spdx.dev/Document/v2.3 證明能證實 SBOM 由誰產生、對應哪個建置產物,但不會讓 SBOM 更完整。
4. 在建置期間記錄
CRACI 會在作業執行時記錄 SBOM。您只需將 runs-on 改為 craci:
jobs:
build:
runs-on: craci # was: ubuntu-latest 接著,執行器上具備套件感知能力的代理伺服器會記錄作業擷取的每個套件,包括從 CI 快取還原的套件,以及任何鎖定檔都未列出的隱藏相依套件,例如安裝腳本下載的程式碼。由於不需要安排產生工具步驟的位置,時機問題也就不存在了。每份 CycloneDX 或 SPDX 格式的 SBOM 都會依作業與快取標示其完整性,API 則會回傳 SBOM、網路追蹤記錄與來源證明。包括 CRACI GitHub App 與網路設定在內的設定方式,請參閱 CRACI 文件;各完整性狀態的意義,請參閱作業與快取的 SBOM 完整性。
該使用哪一種
- 快速取得儲存庫的清單:相依關係圖匯出。
- 容器映像檔的 SBOM:針對映像檔執行產生工具步驟。
- 證明 SBOM 由誰產生、對應哪個建置產物:在上述任一做法之上加入證明。
- 建置實際使用內容的紀錄,用於漏洞應變或 Cyber Resilience Act(CRA):建置時記錄。請參閱 SBOM 工具比較。
GitHub Actions 中的 SBOM:常見問題
如何在 GitHub Actions 中產生 SBOM?
在安裝步驟之後加入一個產生工具步驟。最簡短的是 anchore/sbom-action@v0,它會對工作區執行 Syft,並將 SPDX JSON SBOM 上傳為工作流程建置產物。若需要簽章的 SBOM,請將檔案傳給 actions/attest@v4,並使用 sbom-path。
GitHub 會自動產生 SBOM 嗎?
GitHub 可以從 Insights 分頁或 REST API,將儲存庫的相依關係圖匯出為 SPDX SBOM。它描述的是儲存庫中的 manifest 與 lockfile,而不是特定的建置,因此不會顯示工作流程下載的工具或套件。
哪個 action 能在 GitHub Actions 中產生 SBOM?
anchore/sbom-action 會執行 Syft。預設會掃描工作區目錄並輸出 SPDX JSON;也可以改為掃描容器映像檔,將 SBOM 上傳為工作流程建置產物,並附加到版本發布中。
SBOM 工作流程需要哪些權限?
anchore/sbom-action 需要 contents: write,若要將 SBOM 附加到版本發布,還需要 actions: read。以 actions/attest 簽章需要 id-token: write 與 attestations: write,將證明推送到容器 registry 時還需要 packages: write。
如何在 GitHub Actions 中為 SBOM 簽章?
使用 GitHub 的建置產物證明。actions/attest 會以 Sigstore 為 SPDX 或 CycloneDX JSON SBOM 簽章,並將其綁定到建置產物;請以 gh attestation verify 驗證。actions/attest-sbom 即將被淘汰,由 actions/attest 取代,目前它已改為包裝 actions/attest。
如何在 GitHub Actions 中為容器映像檔產生 SBOM?
以 image 輸入取代 path,將映像檔傳給 anchore/sbom-action。若要簽章,請將映像檔名稱與 digest 傳給 actions/attest,透過 subject-name 與 subject-digest 指定,設定 push-to-registry: true,並以 gh attestation verify oci://IMAGE 驗證。
工作流程應該產生 SPDX 還是 CycloneDX?
取決於讀取 SBOM 的工具需要哪一種。相依關係圖匯出僅支援 SPDX,cdxgen 則輸出 CycloneDX。anchore/sbom-action 兩者皆可輸出,actions/attest 兩者皆可接受。請參閱 CycloneDX 與 SPDX 比較。
SBOM 步驟應該在建置之前還是之後執行?
在相依套件安裝完成之後,否則會遺漏它們。即使如此,它看到的也只是磁碟上的內容,而不是作業下載後又移除的內容,或腳本擷取的內容。在建置期間記錄可以避開時機問題。