Files
Charon/docs/plans/archive/supply_chain_security_implementation.md.backup
2026-03-04 18:34:49 +00:00

1740 lines
59 KiB
Plaintext

# Supply Chain Security Implementation Plan
**Version**: 2.0
**Date**: 2026-01-10
**Updated**: 2026-01-10 (Supervisor Feedback)
**Target Completion**: Phase 3 (3-4 weeks)
**Assignee**: DevOps Agent
---
## Executive Summary
Implement a comprehensive supply chain security solution for Charon using **SBOM verification** (Software Bill of Materials), **Cosign** (artifact signing), and **SLSA** (provenance attestation). This plan integrates signing and verification into GitHub Actions workflows, creates production-ready GitHub Skills for local development, adds VS Code tasks for developer workflows, and includes complete key management procedures.
**Key Goals**:
1. Automate SBOM generation, verification, and vulnerability scanning
2. Sign all Docker images and binaries with Cosign (keyless and local key support)
3. Generate and verify SLSA provenance for all releases
4. Enable local testing via complete, tested GitHub Skills
5. Update Management agent Definition of Done with supply chain verification
6. Establish performance baselines and monitoring
7. Implement fallback mechanisms for service outages
**Implementation Priority** (Revised):
- **Phase 1**: SBOM Verification (Week 1) - Foundation for supply chain visibility
- **Phase 2**: Cosign Integration (Week 2) - Artifact signing and integrity
- **Phase 3**: SLSA Provenance (Week 3) - Build transparency and attestation
---
## Background
### Current State
- ✅ SBOM generation exists in `docker-build.yml` (Anchore SBOM action)
- ✅ SBOM attestation exists in `docker-build.yml` (actions/attest-sbom)
- ❌ No SBOM vulnerability scanning or semantic diffing
- ❌ No Cosign signing for artifacts
- ❌ No SLSA provenance generation
- ❌ No verification workflows with PR triggers
- ❌ No local testing skills (complete implementation)
- ❌ No local key management procedures
- ❌ No performance baselines or monitoring
- ❌ No Rekor fallback mechanisms
### Security Requirements
- **SLSA Level 2+**: Provenance generation with isolated build system
- **Keyless Signing**: Use GitHub OIDC tokens (no long-lived keys in CI)
- **Local Key Management**: Secure procedures for development signing with key-based signing
- **Transparency Logs**: All signatures stored in Rekor with fallback for outages
- **Verification**: Automated verification in CI (including PRs) and pre-deployment
- **Developer Access**: Complete, tested local signing/verification via Skills
- **Vulnerability Scanning**: Automated SBOM scanning with Grype/Trivy
- **Semantic SBOM Diffing**: Use sbom-diff or similar for component analysis
- **Performance Monitoring**: Baseline measurements and continuous tracking
- **Air-Gapped Support**: Local signing without internet connectivity
- **Standardization**: SPDX format for all SBOMs
---
## Architecture Overview
### Component Stack
```
┌─────────────────────────────────────────────────────────────┐
│ GitHub Actions (CI/CD) │
├─────────────────────────────────────────────────────────────┤
│ Workflow: docker-build.yml │
│ ├─ Build Docker Image │
│ ├─ Generate SBOM (SPDX format) [ENHANCED] │
│ ├─ Scan SBOM with Grype/Trivy [NEW] │
│ ├─ Diff SBOM with baseline [NEW] │
│ ├─ Sign with Cosign (keyless OIDC) [NEW] │
│ ├─ Generate SLSA Provenance [NEW] │
│ └─ Attest SBOM (existing, enhanced) │
│ │
│ Workflow: release-goreleaser.yml │
│ ├─ Build Binaries │
│ ├─ Sign with GoReleaser hooks [NEW] │
│ ├─ Generate SLSA Provenance [NEW] │
│ └─ Attach to GitHub Release │
│ │
│ Workflow: supply-chain-verify.yml [NEW] │
│ ├─ Trigger: releases, PRs, schedule │
│ ├─ Verify Cosign Signatures (with Rekor fallback) │
│ ├─ Verify SLSA Provenance │
│ ├─ Verify SBOM (semantic diff + vuln scan) │
│ └─ Generate verification report │
├─────────────────────────────────────────────────────────────┤
│ GitHub Skills │
├─────────────────────────────────────────────────────────────┤
│ security-verify-sbom [NEW, COMPLETE] │
│ security-sign-cosign [NEW, COMPLETE] │
│ security-slsa-provenance [NEW, COMPLETE] │
├─────────────────────────────────────────────────────────────┤
│ VS Code Tasks │
├─────────────────────────────────────────────────────────────┤
│ Security: Verify SBOM [NEW] │
│ Security: Sign with Cosign [NEW] │
│ Security: Generate SLSA Provenance [NEW] │
│ Security: Full Supply Chain Audit [NEW] │
├─────────────────────────────────────────────────────────────┤
│ Local Key Management │
├─────────────────────────────────────────────────────────────┤
│ ├─ Key generation procedures │
│ ├─ Secure storage with encryption │
│ ├─ Air-gapped signing support │
│ └─ Key rotation and backup │
├─────────────────────────────────────────────────────────────┤
│ Performance Monitoring │
├─────────────────────────────────────────────────────────────┤
│ ├─ Build time impact tracking │
│ ├─ Verification duration metrics │
│ └─ Alert thresholds and dashboards │
└─────────────────────────────────────────────────────────────┘
```
---
## Phase 1: SBOM Verification (Week 1)
**Priority**: CRITICAL - Foundation for supply chain visibility
**Status**: New implementation with enhancements
### 1.1 Workflow Enhancement
#### File: `.github/workflows/docker-build.yml`
**Location**: Enhance existing SBOM generation (around line 160)
**Changes**:
1. Standardize SBOM format to SPDX
2. Add vulnerability scanning with Grype
3. Implement semantic SBOM diffing
4. Add baseline comparison
```yaml
# Replace existing SBOM generation step with enhanced version
- name: Generate SBOM (SPDX Format)
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.21.0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }}
format: spdx-json
output-file: sbom-spdx.json
upload-artifact: true
upload-release-assets: true
- name: Scan SBOM for Vulnerabilities
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
run: |
# Install Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# Scan SBOM
echo "Scanning SBOM for vulnerabilities..."
grype sbom:sbom-spdx.json -o json > vuln-results.json
grype sbom:sbom-spdx.json -o table
# Check for critical/high vulnerabilities
CRITICAL_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' vuln-results.json)
HIGH_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "High")] | length' vuln-results.json)
echo "Critical vulnerabilities: ${CRITICAL_COUNT}"
echo "High vulnerabilities: ${HIGH_COUNT}"
if [[ ${CRITICAL_COUNT} -gt 0 ]]; then
echo "❌ Critical vulnerabilities found - review required"
# Don't fail build, but warn
echo "::warning::${CRITICAL_COUNT} critical vulnerabilities found in SBOM"
fi
- name: SBOM Semantic Diff
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
continue-on-error: true
run: |
# Install sbom-diff tool
go install github.com/interlynk-io/sbomasm/cmd/sbomasm@latest
# Download previous SBOM if exists
if gh release view latest --json assets -q '.assets[] | select(.name == "sbom-spdx.json") | .url' > /dev/null 2>&1; then
gh release download latest --pattern "sbom-spdx.json" --output sbom-baseline.json
echo "Comparing current SBOM with baseline..."
# Compare component counts
BASELINE_COUNT=$(jq '.packages | length' sbom-baseline.json)
CURRENT_COUNT=$(jq '.packages | length' sbom-spdx.json)
echo "Baseline packages: ${BASELINE_COUNT}"
echo "Current packages: ${CURRENT_COUNT}"
echo "Delta: $((CURRENT_COUNT - BASELINE_COUNT))"
# Identify added/removed packages
jq -r '.packages[].name' sbom-baseline.json | sort > baseline-packages.txt
jq -r '.packages[].name' sbom-spdx.json | sort > current-packages.txt
echo "Removed packages:"
comm -23 baseline-packages.txt current-packages.txt || true
echo "Added packages:"
comm -13 baseline-packages.txt current-packages.txt || true
else
echo "No baseline SBOM found - this will become the baseline"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Attest SBOM
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
uses: actions/attest-sbom@210638bd5681be69f5648391e3b0a389d2d08e5b # v3.0.0
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
sbom-path: sbom-spdx.json
push-to-registry: true
```
### 1.2 Workflow Creation: Verification with PR Triggers
#### File: `.github/workflows/supply-chain-verify.yml` [NEW]
**Location**: `.github/workflows/supply-chain-verify.yml`
**Purpose**: Automated verification workflow triggered on releases, PRs, and schedules
```yaml
name: Supply Chain Verification
on:
release:
types: [published]
pull_request: # NEW: Add PR trigger
paths:
- '.github/workflows/docker-build.yml'
- '.github/workflows/release-goreleaser.yml'
- 'Dockerfile'
- 'backend/**'
- 'frontend/**'
schedule:
# Run weekly on Mondays at 00:00 UTC
- cron: '0 0 * * 1'
workflow_dispatch:
permissions:
contents: read
packages: read
id-token: write # NEW: OIDC token for keyless verification
attestations: write # NEW: Create/verify attestations
security-events: write
pull-requests: write # NEW: Comment on PRs
jobs:
verify-sbom:
name: Verify SBOM
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Verification Tools
run: |
# Install Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# Install Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# Install sbom-diff
go install github.com/interlynk-io/sbomasm/cmd/sbomasm@latest
- name: Determine Image Tag
id: tag
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
TAG="pr-${{ github.event.pull_request.number }}"
else
TAG="latest"
fi
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Verify SBOM Completeness
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Verifying SBOM for ${IMAGE}..."
# Generate fresh SBOM
syft ${IMAGE} -o spdx-json > sbom-generated.json
# Download attested SBOM
gh attestation download ${IMAGE} --digest-alg sha256 \
--predicate-type https://spdx.dev/Document \
--output sbom-attested.json || {
echo "⚠️ No attested SBOM found - may be PR build"
exit 0
}
# Semantic comparison using sbomasm
GENERATED_COUNT=$(jq '.packages | length' sbom-generated.json)
ATTESTED_COUNT=$(jq '.packages | length' sbom-attested.json)
echo "Generated SBOM packages: ${GENERATED_COUNT}"
echo "Attested SBOM packages: ${ATTESTED_COUNT}"
# Allow 5% variance
DIFF=$((GENERATED_COUNT - ATTESTED_COUNT))
DIFF_ABS=${DIFF#-}
DIFF_PCT=$((100 * DIFF_ABS / GENERATED_COUNT))
if [[ ${DIFF_PCT} -gt 5 ]]; then
echo "❌ SBOM package mismatch exceeds 5%"
exit 1
fi
echo "✅ SBOM verification passed (${DIFF_PCT}% variance)"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Scan for Vulnerabilities
continue-on-error: true
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Scanning for vulnerabilities..."
grype ${IMAGE} -o json > vuln-scan.json
grype ${IMAGE} -o table
CRITICAL=$(jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' vuln-scan.json)
HIGH=$(jq '[.matches[] | select(.vulnerability.severity == "High")] | length' vuln-scan.json)
echo "Critical: ${CRITICAL}, High: ${HIGH}"
if [[ ${CRITICAL} -gt 0 ]]; then
echo "::warning::${CRITICAL} critical vulnerabilities found"
fi
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const fs = require('fs');
const vulnData = JSON.parse(fs.readFileSync('vuln-scan.json', 'utf8'));
const critical = vulnData.matches.filter(m => m.vulnerability.severity === 'Critical').length;
const high = vulnData.matches.filter(m => m.vulnerability.severity === 'High').length;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## 🔒 Supply Chain Verification\n\n✅ SBOM verified\n📊 Vulnerabilities: ${critical} Critical, ${high} High\n\n[View full report](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`
});
verify-docker-image:
name: Verify Docker Image Supply Chain
runs-on: ubuntu-latest
if: github.event_name == 'release'
needs: verify-sbom
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Verification Tools
run: |
# Install Cosign (pinned to commit SHA)
curl -sLO https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64
echo "4e84f155f98be2c2d3e63dea0e80b0ca5b4d843f5f4b1d3e8c9b7e4e7c0e0e0e cosign-linux-amd64" | sha256sum -c
sudo install cosign-linux-amd64 /usr/local/bin/cosign
rm cosign-linux-amd64
# Install SLSA Verifier (pinned to commit SHA)
curl -sLO https://github.com/slsa-framework/slsa-verifier/releases/download/v2.6.0/slsa-verifier-linux-amd64
echo "7e4c88e0de4b5e3e0e8f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f slsa-verifier-linux-amd64" | sha256sum -c
sudo install slsa-verifier-linux-amd64 /usr/local/bin/slsa-verifier
rm slsa-verifier-linux-amd64
- name: Determine Image Tag
id: tag
run: |
TAG="${{ github.event.release.tag_name }}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Verify Cosign Signature with Rekor Fallback
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Verifying Cosign signature for ${IMAGE}..."
# Try with Rekor
if cosign verify ${IMAGE} \
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" 2>&1; then
echo "✅ Cosign signature verified (with Rekor)"
else
echo "⚠️ Rekor verification failed, trying offline verification..."
# Fallback: verify without Rekor
if cosign verify ${IMAGE} \
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
--insecure-ignore-tlog 2>&1; then
echo "✅ Cosign signature verified (offline mode)"
echo "::warning::Verified without Rekor - transparency log unavailable"
else
echo "❌ Signature verification failed"
exit 1
fi
fi
- name: Verify SLSA Provenance
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Verifying SLSA provenance for ${IMAGE}..."
# Download provenance
gh attestation download ${IMAGE} --digest-alg sha256 \
--predicate-type https://slsa.dev/provenance/v1 \
--output provenance.json
# Verify provenance
slsa-verifier verify-image ${IMAGE} \
--provenance-path provenance.json \
--source-uri github.com/${{ github.repository }}
echo "✅ SLSA provenance verified"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Verification Report
if: always()
run: |
cat << EOF > verification-report.md
# Supply Chain Verification Report
**Image**: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
**Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
**Workflow**: ${{ github.workflow }}
**Run**: ${{ github.run_id }}
## Results
- **SBOM Verification**: ${{ needs.verify-sbom.result }}
- **Cosign Signature**: ${{ job.status }}
- **SLSA Provenance**: ${{ job.status }}
## Verification Failure Recovery
If verification failed:
1. Check workflow logs for detailed error messages
2. Verify signing steps ran successfully in build workflow
3. Confirm attestations were pushed to registry
4. Check Rekor status: https://status.sigstore.dev
5. For Rekor outages, manual verification may be required
6. Re-run build if signatures/provenance are missing
EOF
cat verification-report.md >> $GITHUB_STEP_SUMMARY
verify-release-artifacts:
name: Verify Release Artifacts
runs-on: ubuntu-latest
if: github.event_name == 'release'
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Verification Tools
run: |
# Install Cosign (pinned)
curl -sLO https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64
sudo install cosign-linux-amd64 /usr/local/bin/cosign
rm cosign-linux-amd64
# Install SLSA Verifier (pinned)
curl -sLO https://github.com/slsa-framework/slsa-verifier/releases/download/v2.6.0/slsa-verifier-linux-amd64
sudo install slsa-verifier-linux-amd64 /usr/local/bin/slsa-verifier
rm slsa-verifier-linux-amd64
- name: Download Release Assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG=${{ github.event.release.tag_name }}
gh release download ${TAG} --dir ./release-assets
- name: Verify Artifact Signatures with Fallback
run: |
echo "Verifying Cosign signatures for release artifacts..."
for artifact in ./release-assets/*; do
# Skip signature and certificate files
if [[ "$artifact" == *.sig || "$artifact" == *.pem || "$artifact" == *provenance* ]]; then
continue
fi
if [[ -f "$artifact" ]]; then
echo "Verifying: $(basename $artifact)"
# Try with Rekor
if cosign verify-blob "$artifact" \
--signature "${artifact}.sig" \
--certificate "${artifact}.pem" \
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" 2>&1; then
echo "✅ Verified with Rekor"
else
echo "⚠️ Rekor unavailable, trying offline..."
cosign verify-blob "$artifact" \
--signature "${artifact}.sig" \
--certificate "${artifact}.pem" \
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
--insecure-ignore-tlog
echo "✅ Verified offline"
fi
fi
done
echo "✅ All artifact signatures verified"
- name: Verify Release Provenance
run: |
echo "Verifying SLSA provenance for release..."
if [[ -f "./release-assets/provenance-release.json" ]]; then
slsa-verifier verify-artifact \
--provenance-path ./release-assets/provenance-release.json \
--source-uri github.com/${{ github.repository }}
echo "✅ Release provenance verified"
else
echo "⚠️ No provenance file found"
exit 1
fi
```
### 1.3 GitHub Skill: `security-verify-sbom` (Complete Implementation)
#### File: `.github/skills/security-verify-sbom.SKILL.md`
**Location**: `.github/skills/security-verify-sbom.SKILL.md`
**Content**: Full SKILL.md specification with parameter validation
```markdown
---
name: "security-verify-sbom"
version: "1.0.0"
description: "Verify SBOM completeness, scan for vulnerabilities, and perform semantic diff analysis"
author: "Charon Project"
license: "MIT"
tags: ["security", "sbom", "verification", "supply-chain", "vulnerability-scanning"]
compatibility:
os: ["linux", "darwin"]
shells: ["bash"]
requirements:
- name: "syft"
version: ">=1.17.0"
optional: false
install_url: "https://github.com/anchore/syft"
- name: "grype"
version: ">=0.85.0"
optional: false
install_url: "https://github.com/anchore/grype"
- name: "jq"
version: ">=1.6"
optional: false
environment_variables:
- name: "SBOM_FORMAT"
description: "SBOM format (spdx-json, cyclonedx-json)"
default: "spdx-json"
required: false
- name: "VULN_SCAN_ENABLED"
description: "Enable vulnerability scanning"
default: "true"
required: false
parameters:
- name: "target"
type: "string"
description: "Docker image or file path"
required: true
validation: "^[a-zA-Z0-9:/@._-]+$"
- name: "baseline"
type: "string"
description: "Baseline SBOM file path for comparison"
required: false
default: ""
- name: "vuln_scan"
type: "boolean"
description: "Run vulnerability scan"
required: false
default: true
exit_codes:
0: "Verification successful"
1: "Verification failed or critical vulnerabilities found"
2: "Missing dependencies or invalid parameters"
---
# Security: Verify SBOM
Verify Software Bill of Materials (SBOM) completeness, scan for vulnerabilities, and perform semantic diff analysis.
## Features
- Generate SBOM in SPDX format (standardized)
- Compare with baseline SBOM (semantic diff)
- Scan for vulnerabilities (Critical/High/Medium/Low)
- Validate SBOM structure and completeness
- Support Docker images and local files
- Air-gapped operation support (skip vulnerability scanning)
## Usage
```bash
# Verify Docker image SBOM with vulnerability scan
.github/skills/scripts/skill-runner.sh security-verify-sbom ghcr.io/user/charon:latest
# Verify with baseline comparison
.github/skills/scripts/skill-runner.sh security-verify-sbom charon:local sbom-baseline.json
# Verify local image without vulnerability scan (air-gapped)
VULN_SCAN_ENABLED=false .github/skills/scripts/skill-runner.sh security-verify-sbom charon:local
# Negative test: verify tampered image (should fail)
.github/skills/scripts/skill-runner.sh security-verify-sbom tampered:image
```
## Examples
### Basic Verification
```bash
$ .github/skills/scripts/skill-runner.sh security-verify-sbom charon:test
[INFO] Generating SBOM for charon:test...
[INFO] SBOM contains 247 packages
[INFO] Scanning for vulnerabilities...
[INFO] Found: 0 Critical, 2 High, 15 Medium
✅ Verification complete
```
### With Baseline Comparison
```bash
$ .github/skills/scripts/skill-runner.sh security-verify-sbom charon:latest sbom-baseline.json
[INFO] Generating SBOM for charon:latest...
[INFO] Comparing with baseline...
[INFO] Baseline: 245 packages, Current: 247 packages
[INFO] Added packages: golang.org/x/crypto@v0.30.0, github.com/pkg/errors@v0.9.1
[INFO] Removed packages: (none)
✅ Verification complete (0.8% variance)
### 1.1 Workflow Updates
#### File: `.github/workflows/docker-build.yml`
**Location**: After `steps.build-and-push` (line ~145)
**Changes**:
1. Add Cosign installation step
2. Add Docker image signing step
3. Store signature in Rekor transparency log
```yaml
# Add after "Build and push Docker image" step
- name: Install Cosign
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
uses: sigstore/cosign-installer@v3.8.1
with:
cosign-release: 'v2.4.1'
- name: Sign Docker Image with Cosign
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
env:
DIGEST: ${{ steps.build-and-push.outputs.digest }}
TAGS: ${{ steps.meta.outputs.tags }}
run: |
echo "Signing image with Cosign (keyless OIDC)..."
images=""
for tag in ${TAGS}; do
images+="${tag}@${DIGEST} "
done
# Sign with keyless mode (GitHub OIDC token)
cosign sign --yes ${images}
echo "✅ Image signed and uploaded to Rekor transparency log"
echo "Verification command: cosign verify ${REGISTRY}/${IMAGE_NAME}@${DIGEST} \\"
echo " --certificate-identity-regexp='https://github.com/${GITHUB_REPOSITORY}' \\"
echo " --certificate-oidc-issuer='https://token.actions.githubusercontent.com'"
```
#### File: `.github/workflows/release-goreleaser.yml`
**Location**: After `Run GoReleaser` step (line ~60)
**Changes**:
1. Add Cosign installation
2. Sign all release binaries
3. Upload signatures as release assets
```yaml
# Add after "Run GoReleaser" step
- name: Install Cosign
uses: sigstore/cosign-installer@v3.8.1
with:
cosign-release: 'v2.4.1'
- name: Sign Release Artifacts with Cosign
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Signing release artifacts..."
# Get release tag
TAG=${GITHUB_REF#refs/tags/}
# Download artifacts from release
gh release download ${TAG} --dir ./release-artifacts
# Sign each binary
for artifact in ./release-artifacts/*; do
if [[ -f "$artifact" && ! "$artifact" == *.sig && ! "$artifact" == *.pem ]]; then
echo "Signing: $(basename $artifact)"
cosign sign-blob --yes --output-signature="${artifact}.sig" \
--output-certificate="${artifact}.pem" \
"$artifact"
fi
done
# Upload signatures back to release
gh release upload ${TAG} ./release-artifacts/*.sig ./release-artifacts/*.pem --clobber
echo "✅ All artifacts signed and signatures uploaded to release"
```
### 1.2 GitHub Skill: `security-sign-cosign`
#### File: `.github/skills/security-sign-cosign.SKILL.md`
**Location**: `.github/skills/security-sign-cosign.SKILL.md`
**Content**: Full SKILL.md specification (see appendix A1)
#### File: `.github/skills/security-sign-cosign-scripts/run.sh`
**Location**: `.github/skills/security-sign-cosign-scripts/run.sh`
**Content**: Bash script implementing local Cosign signing (see appendix A2)
**Key Features**:
- Sign local Docker images
- Sign arbitrary files (binaries, archives)
- Support keyless (OIDC) and key-based signing
- Verify signatures after signing
- Output signature files (.sig, .pem)
### 1.3 VS Code Task
#### File: `.vscode/tasks.json`
**Location**: Add to `tasks` array
```json
{
"label": "Security: Sign with Cosign",
"type": "shell",
"command": ".github/skills/scripts/skill-runner.sh security-sign-cosign",
"group": "test",
"problemMatcher": []
}
```
### 1.4 Secrets Configuration
**No secrets required** for keyless signing (uses GitHub OIDC tokens automatically).
Optional: For key-based signing (local development):
- `COSIGN_PRIVATE_KEY`: Base64-encoded private key
- `COSIGN_PASSWORD`: Password for private key
### 1.5 Testing & Validation
**Acceptance Criteria**:
- [ ] Docker images signed in `docker-build.yml` workflow
- [ ] Release binaries signed in `release-goreleaser.yml` workflow
- [ ] Signatures visible in Rekor transparency log
- [ ] Local skill can sign test images
- [ ] VS Code task executes successfully
- [ ] Signature verification passes via `cosign verify`
---
## Phase 2: SLSA Provenance (Week 2)
### 2.1 Workflow Updates
#### File: `.github/workflows/docker-build.yml`
**Location**: After Cosign signing step
**Changes**:
1. Generate SLSA provenance using `slsa-github-generator`
2. Attach provenance to image as attestation
```yaml
- name: Generate SLSA Provenance
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
uses: slsa-framework/slsa-github-generator/.github/actions/generator-generic-slsa3@v2.1.0
with:
base64-subjects: ${{ steps.build-and-push.outputs.digest }}
provenance-name: "provenance.json"
upload-assets: true
- name: Attest Provenance to Image
if: github.event_name != 'pull_request' && steps.skip.outputs.skip_build != 'true'
uses: actions/attest-build-provenance@v2.1.0
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true
```
#### File: `.github/workflows/release-goreleaser.yml`
**Location**: After Cosign signing step
**Changes**:
1. Generate SLSA provenance for all release artifacts
2. Upload provenance as release asset
```yaml
- name: Generate SLSA Provenance for Release
uses: slsa-framework/slsa-github-generator/.github/actions/generator-generic-slsa3@v2.1.0
with:
base64-subjects: |
${{ hashFiles('release-artifacts/*') }}
provenance-name: "provenance-release.json"
upload-assets: true
upload-tag-name: ${{ github.ref_name }}
```
### 2.2 GitHub Skill: `security-slsa-provenance`
#### File: `.github/skills/security-slsa-provenance.SKILL.md`
**Location**: `.github/skills/security-slsa-provenance.SKILL.md`
**Content**: Full SKILL.md specification (see appendix B1)
#### File: `.github/skills/security-slsa-provenance-scripts/run.sh`
**Location**: `.github/skills/security-slsa-provenance-scripts/run.sh`
**Content**: Bash script implementing SLSA provenance generation and verification (see appendix B2)
**Key Features**:
- Generate SLSA provenance for local artifacts
- Verify provenance against policy
- Parse and display provenance metadata
- Check SLSA level compliance
### 2.3 VS Code Task
#### File: `.vscode/tasks.json`
**Location**: Add to `tasks` array
```json
{
"label": "Security: Generate SLSA Provenance",
"type": "shell",
"command": ".github/skills/scripts/skill-runner.sh security-slsa-provenance",
"group": "test",
"problemMatcher": []
}
```
### 2.4 Testing & Validation
**Acceptance Criteria**:
- [ ] SLSA provenance generated for Docker images
- [ ] SLSA provenance generated for release binaries
- [ ] Provenance attestations pushed to registry
- [ ] Provenance files uploaded to GitHub releases
- [ ] Local skill can generate/verify provenance
- [ ] VS Code task executes successfully
- [ ] SLSA level 2+ compliance verified
---
## Phase 3: SBOM Verification (Week 3)
### 3.1 Workflow Creation
#### File: `.github/workflows/supply-chain-verify.yml` [NEW]
**Location**: `.github/workflows/supply-chain-verify.yml`
**Purpose**: Automated verification workflow triggered on releases and schedules
```yaml
name: Supply Chain Verification
on:
release:
types: [published]
schedule:
# Run weekly on Mondays at 00:00 UTC
- cron: '0 0 * * 1'
workflow_dispatch:
permissions:
contents: read
packages: read
security-events: write
jobs:
verify-docker-image:
name: Verify Docker Image Supply Chain
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Verification Tools
run: |
# Install Cosign
curl -sLO https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64
sudo install cosign-linux-amd64 /usr/local/bin/cosign
rm cosign-linux-amd64
# Install SLSA Verifier
curl -sLO https://github.com/slsa-framework/slsa-verifier/releases/download/v2.6.0/slsa-verifier-linux-amd64
sudo install slsa-verifier-linux-amd64 /usr/local/bin/slsa-verifier
rm slsa-verifier-linux-amd64
# Install Syft (SBOM generation/verification)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- name: Determine Image Tag
id: tag
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
else
TAG="latest"
fi
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Verify Cosign Signature
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Verifying Cosign signature for ${IMAGE}..."
cosign verify ${IMAGE} \
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"
echo "✅ Cosign signature verified"
- name: Verify SLSA Provenance
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Verifying SLSA provenance for ${IMAGE}..."
# Download provenance
gh attestation download ${IMAGE} --digest-alg sha256 \
--predicate-type https://slsa.dev/provenance/v1 \
--output provenance.json
# Verify provenance
slsa-verifier verify-image ${IMAGE} \
--provenance-path provenance.json \
--source-uri github.com/${{ github.repository }}
echo "✅ SLSA provenance verified"
- name: Verify SBOM Completeness
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
run: |
echo "Verifying SBOM for ${IMAGE}..."
# Generate fresh SBOM
syft ${IMAGE} -o cyclonedx-json > sbom-generated.json
# Download attested SBOM
gh attestation download ${IMAGE} --digest-alg sha256 \
--predicate-type https://spdx.dev/Document \
--output sbom-attested.json
# Compare component counts
GENERATED_COUNT=$(jq '.components | length' sbom-generated.json)
ATTESTED_COUNT=$(jq '.components | length' sbom-attested.json)
echo "Generated SBOM components: ${GENERATED_COUNT}"
echo "Attested SBOM components: ${ATTESTED_COUNT}"
# Allow 5% variance
DIFF=$((GENERATED_COUNT - ATTESTED_COUNT))
DIFF_PCT=$((100 * DIFF / GENERATED_COUNT))
if [[ ${DIFF_PCT#-} -gt 5 ]]; then
echo "❌ SBOM component mismatch exceeds 5%"
exit 1
fi
echo "✅ SBOM verification passed"
- name: Create Verification Report
if: always()
run: |
cat << EOF > verification-report.md
# Supply Chain Verification Report
**Image**: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
**Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
**Workflow**: ${{ github.workflow }}
**Run**: ${{ github.run_id }}
## Results
- **Cosign Signature**: ${{ job.status }}
- **SLSA Provenance**: ${{ job.status }}
- **SBOM Verification**: ${{ job.status }}
## Next Steps
If any verification failed:
1. Check workflow logs for detailed error messages
2. Verify signing steps ran successfully in build workflow
3. Confirm attestations were pushed to registry
4. Re-run build if necessary
EOF
cat verification-report.md >> $GITHUB_STEP_SUMMARY
verify-release-artifacts:
name: Verify Release Artifacts
runs-on: ubuntu-latest
if: github.event_name == 'release'
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Verification Tools
run: |
# Install Cosign
curl -sLO https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64
sudo install cosign-linux-amd64 /usr/local/bin/cosign
rm cosign-linux-amd64
# Install SLSA Verifier
curl -sLO https://github.com/slsa-framework/slsa-verifier/releases/download/v2.6.0/slsa-verifier-linux-amd64
sudo install slsa-verifier-linux-amd64 /usr/local/bin/slsa-verifier
rm slsa-verifier-linux-amd64
- name: Download Release Assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG=${{ github.event.release.tag_name }}
gh release download ${TAG} --dir ./release-assets
- name: Verify Artifact Signatures
run: |
echo "Verifying Cosign signatures for release artifacts..."
for artifact in ./release-assets/*; do
# Skip signature and certificate files
if [[ "$artifact" == *.sig || "$artifact" == *.pem || "$artifact" == *provenance* ]]; then
continue
fi
if [[ -f "$artifact" ]]; then
echo "Verifying: $(basename $artifact)"
# Verify blob signature
cosign verify-blob "$artifact" \
--signature "${artifact}.sig" \
--certificate "${artifact}.pem" \
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"
fi
done
echo "✅ All artifact signatures verified"
- name: Verify Release Provenance
run: |
echo "Verifying SLSA provenance for release..."
if [[ -f "./release-assets/provenance-release.json" ]]; then
slsa-verifier verify-artifact \
--provenance-path ./release-assets/provenance-release.json \
--source-uri github.com/${{ github.repository }}
echo "✅ Release provenance verified"
else
echo "⚠️ No provenance file found"
exit 1
fi
```
### 3.2 GitHub Skill: `security-verify-sbom`
#### File: `.github/skills/security-verify-sbom.SKILL.md`
**Location**: `.github/skills/security-verify-sbom.SKILL.md`
**Content**: Full SKILL.md specification (see appendix C1)
#### File: `.github/skills/security-verify-sbom-scripts/run.sh`
**Location**: `.github/skills/security-verify-sbom-scripts/run.sh`
**Content**: Bash script implementing SBOM verification (see appendix C2)
**Key Features**:
- Generate SBOM from local Docker images
- Compare SBOM against attested version
- Check for known vulnerabilities in SBOM
- Validate SBOM format and completeness
- Report drift between builds
### 3.3 VS Code Tasks
#### File: `.vscode/tasks.json`
**Location**: Add to `tasks` array
```json
{
"label": "Security: Verify SBOM",
"type": "shell",
"command": ".github/skills/scripts/skill-runner.sh security-verify-sbom",
"group": "test",
"problemMatcher": []
},
{
"label": "Security: Full Supply Chain Audit",
"type": "shell",
"dependsOn": [
"Security: Sign with Cosign",
"Security: Generate SLSA Provenance",
"Security: Verify SBOM"
],
"dependsOrder": "sequence",
"command": "echo '✅ Supply chain audit complete'",
"group": "test",
"problemMatcher": []
}
```
### 3.4 Testing & Validation
**Acceptance Criteria**:
- [ ] Verification workflow runs on releases
- [ ] Verification workflow runs weekly
- [ ] Docker image signatures verified
- [ ] Release artifact signatures verified
- [ ] SLSA provenance verified
- [ ] SBOM completeness verified
- [ ] Local skill can verify SBOM
- [ ] VS Code tasks execute successfully
- [ ] Full audit task chains all verifications
---
## Management Agent Definition of Done Updates
### File: `.github/agents/Managment.agent.md`
**Location**: Section `## DEFINITION OF DONE ##` (line 70)
**Changes**: Add supply chain verification as mandatory step
```markdown
## DEFINITION OF DONE ##
The task is not complete until ALL of the following pass with zero issues:
1. **Coverage Tests (MANDATORY - Verify Explicitly)**:
- **Backend**: Ensure `Backend_Dev` ran VS Code task "Test: Backend with Coverage" or `scripts/go-test-coverage.sh`
- **Frontend**: Ensure `Frontend_Dev` ran VS Code task "Test: Frontend with Coverage" or `scripts/frontend-test-coverage.sh`
- **Why**: These are in manual stage of pre-commit for performance. Subagents MUST run them via VS Code tasks or scripts.
- Minimum coverage: 85% for both backend and frontend.
- All tests must pass with zero failures.
2. **Type Safety (Frontend)**:
- Ensure `Frontend_Dev` ran VS Code task "Lint: TypeScript Check" or `npm run type-check`
- **Why**: This check is in manual stage of pre-commit for performance. Subagents MUST run it explicitly.
3. **Pre-commit Hooks**: Ensure `QA_Security` ran `pre-commit run --all-files` (fast hooks only; coverage was verified in step 1)
4. **Security Scans**: Ensure `QA_Security` ran CodeQL and Trivy with zero Critical or High severity issues
5. **Supply Chain Security (NEW - MANDATORY for releases)**: [NEW]
- **Docker Images**: Ensure DevOps signed images with Cosign and generated SLSA provenance
- **Release Artifacts**: Ensure DevOps signed all binaries and attached SLSA provenance
- **SBOM Verification**: Ensure DevOps verified SBOM completeness
- **Verification**: Run VS Code task "Security: Full Supply Chain Audit" to verify all attestations
- **Why**: Supply chain attacks are a critical threat. All artifacts must be cryptographically signed and provenance-verified.
- **When**: Required for all releases, recommended for development builds
6. **Linting**: All language-specific linters must pass
**Your Role**: You delegate implementation to subagents, but YOU are responsible for verifying they completed the Definition of Done. Do not accept "DONE" from a subagent until you have confirmed they ran coverage tests, type checks, security scans, **and supply chain verification** explicitly.
**Critical Note**: Leaving this unfinished prevents commit, push, and leaves users open to security concerns. All issues must be fixed regardless of whether they are unrelated to the original task. This rule must never be skipped. It is non-negotiable anytime any bit of code is added or changed.
```
---
## File Changes Summary
### Files to Create (10 new files)
1. `.github/skills/security-sign-cosign.SKILL.md`
2. `.github/skills/security-sign-cosign-scripts/run.sh`
3. `.github/skills/security-slsa-provenance.SKILL.md`
4. `.github/skills/security-slsa-provenance-scripts/run.sh`
5. `.github/skills/security-verify-sbom.SKILL.md`
6. `.github/skills/security-verify-sbom-scripts/run.sh`
7. `.github/workflows/supply-chain-verify.yml`
8. `docs/plans/supply_chain_security_implementation.md` (this file)
9. `docs/reports/supply_chain_verification_report_template.md`
10. `.github/skills/examples/supply-chain-example.sh`
### Files to Modify (3 existing files)
1. `.github/workflows/docker-build.yml`
- Add Cosign installation step (after line 145)
- Add Cosign signing step (after build-and-push)
- Add SLSA provenance generation (after signing)
2. `.github/workflows/release-goreleaser.yml`
- Add Cosign installation step (after line 60)
- Add artifact signing step (after GoReleaser)
- Add SLSA provenance generation (after signing)
3. `.vscode/tasks.json`
- Add 4 new tasks (lines to append to tasks array)
4. `.github/agents/Managment.agent.md`
- Update Definition of Done section (line 70)
---
## Secret Requirements
### GitHub Secrets (Repository Level)
**None required** for keyless signing. The following are **optional** for advanced scenarios:
1. `COSIGN_PRIVATE_KEY` (Optional)
- **Purpose**: Key-based signing for non-CI environments
- **Format**: Base64-encoded private key
- **Generation**: `cosign generate-key-pair`
- **Usage**: Local development, air-gapped signing
2. `COSIGN_PASSWORD` (Optional)
- **Purpose**: Password for private key
- **Format**: String
- **Usage**: Decrypt COSIGN_PRIVATE_KEY
### GitHub Permissions (Workflow Level)
Required permissions for workflows:
```yaml
permissions:
contents: write # Upload signatures to releases
packages: write # Push attestations to registry
id-token: write # OIDC token for keyless signing
attestations: write # Create attestations
security-events: write # Upload verification results
```
### Environment Variables (CI/CD)
Default values work for standard setup:
- `COSIGN_EXPERIMENTAL=1` (Enable keyless signing)
- `COSIGN_YES=true` (Non-interactive mode)
- `SLSA_LEVEL=2` (Minimum SLSA level)
---
## Verification & Testing Plan
### Phase 1 Testing (Cosign)
**Test Case 1.1**: Docker Image Signing
```bash
# Trigger workflow
git tag -a v1.0.0-rc1 -m "Test release"
git push origin v1.0.0-rc1
# Verify signature
cosign verify ghcr.io/$USER/charon:v1.0.0-rc1 \
--certificate-identity-regexp="https://github.com/$USER/charon" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"
```
**Test Case 1.2**: Local Signing via Skill
```bash
# Build local image
docker build -t charon:test .
# Sign with skill
.github/skills/scripts/skill-runner.sh security-sign-cosign docker charon:test
# Verify signature
cosign verify charon:test --key cosign.pub
```
**Test Case 1.3**: VS Code Task
```bash
# Open Command Palette (Ctrl+Shift+P)
# Type: "Tasks: Run Task"
# Select: "Security: Sign with Cosign"
# Verify output shows successful signing
```
### Phase 2 Testing (SLSA)
**Test Case 2.1**: SLSA Provenance Generation
```bash
# Check release assets
gh release view v1.0.0-rc1 --json assets
# Download provenance
gh attestation download ghcr.io/$USER/charon:v1.0.0-rc1 \
--predicate-type https://slsa.dev/provenance/v1
# Verify provenance
slsa-verifier verify-image ghcr.io/$USER/charon:v1.0.0-rc1 \
--source-uri github.com/$USER/charon
```
**Test Case 2.2**: Local Provenance via Skill
```bash
# Generate provenance for local artifact
.github/skills/scripts/skill-runner.sh security-slsa-provenance generate charon-binary
# Verify provenance
.github/skills/scripts/skill-runner.sh security-slsa-provenance verify charon-binary
```
### Phase 3 Testing (SBOM)
**Test Case 3.1**: SBOM Verification Workflow
```bash
# Trigger verification workflow
gh workflow run supply-chain-verify.yml
# Check results
gh run list --workflow=supply-chain-verify.yml --limit 1
```
**Test Case 3.2**: Local SBOM Verification via Skill
```bash
# Verify SBOM
.github/skills/scripts/skill-runner.sh security-verify-sbom ghcr.io/$USER/charon:latest
# Check output for component counts and vulnerabilities
```
**Test Case 3.3**: Full Supply Chain Audit Task
```bash
# Run complete audit via VS Code
# Tasks: Run Task -> Security: Full Supply Chain Audit
# Verify all three sub-tasks complete successfully
```
### Integration Testing
**End-to-End Test**: Release Pipeline
1. Create feature branch
2. Make code change
3. Create PR
4. Merge to main
5. Create release tag
6. Verify workflow builds and signs artifacts
7. Run verification workflow
8. Download release assets
9. Verify all signatures and attestations locally
**Success Criteria**:
- All workflows complete without errors
- Signatures verify successfully
- Provenance matches expected source
- SBOM contains all dependencies
- Rekor transparency log contains entries
---
## Rollout Strategy
### Development Environment (Week 1)
- Deploy Phase 1 (Cosign) to development branch
- Test with beta releases
- Validate skill execution locally
- Gather developer feedback
### Staging Environment (Week 2)
- Deploy Phase 2 (SLSA) to development branch
- Test full signing pipeline
- Validate provenance generation
- Performance testing
### Production Environment (Week 3)
- Deploy Phase 3 (SBOM verification) to main branch
- Enable verification workflow
- Monitor for issues
- Update documentation
### Rollback Plan
If critical issues arise:
1. Disable verification workflow (comment out triggers)
2. Remove signing steps from build workflows (make optional with flag)
3. Maintain SBOM generation (already exists, low risk)
4. Document issues and plan remediation
---
## Monitoring & Alerts
### Metrics to Track
1. **Signing Success Rate**: Percentage of successful Cosign signings
2. **Provenance Generation Rate**: Percentage of builds with SLSA provenance
3. **Verification Failure Rate**: Failed verification attempts
4. **Rekor Log Entries**: Transparency log entries created
5. **SBOM Drift**: Variance between builds
### Alerting Rules
1. **Critical**: Signing failure in production release
2. **High**: Verification failure in scheduled check
3. **Medium**: SBOM drift exceeds 10%
4. **Low**: Skill execution failures
### Dashboards
Create GitHub insights dashboard:
- Total artifacts signed (weekly)
- Verification workflow runs (success/failure)
- SLSA level compliance
- Skill usage statistics
---
## Documentation Requirements
### User-Facing Documentation
1. **README.md Updates**
- Add supply chain security section
- Link to verification instructions
- Show verification commands
2. **SECURITY.md Updates**
- Document signing process
- Add verification procedures
- List transparency log URLs
3. **Developer Guide** (new file: `docs/development/supply-chain-security.md`)
- How to sign artifacts locally
- How to verify signatures
- Troubleshooting guide
### Internal Documentation
1. **Runbook**: `docs/runbooks/supply-chain-incident-response.md`
- Signature verification failures
- Provenance mismatches
- SBOM vulnerabilities
2. **Architecture Decision Records**
- Why Cosign over other tools
- Keyless vs key-based signing
- SLSA level rationale
---
## Dependencies & Prerequisites
### Tool Versions
| Tool | Minimum Version | Installation |
|------|----------------|--------------|
| Cosign | v2.4.1 | `go install github.com/sigstore/cosign/v2/cmd/cosign@latest` |
| SLSA Verifier | v2.6.0 | `go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest` |
| Syft | v1.17.0 | `curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh \| sh` |
| GitHub CLI | v2.62.0 | `brew install gh` or [GitHub CLI](https://cli.github.com/) |
### GitHub Actions
| Action | Version | Purpose |
|--------|---------|---------|
| sigstore/cosign-installer | v3.8.1 | Install Cosign in workflows |
| slsa-framework/slsa-github-generator | v2.1.0 | Generate SLSA provenance |
| actions/attest-build-provenance | v2.1.0 | Attest provenance to registry |
| actions/attest-sbom | v3.0.0 | Attest SBOM (existing) |
| anchore/sbom-action | v0.21.0 | Generate SBOM (existing) |
### External Services
- **Rekor Transparency Log**: `https://rekor.sigstore.dev`
- **Fulcio Certificate Authority**: `https://fulcio.sigstore.dev`
- **GitHub Packages**: `ghcr.io` (for attestations)
---
## Risk Assessment
### High Risks
1. **Key Compromise**: Signing keys leaked
- **Mitigation**: Use keyless signing (OIDC tokens)
- **Detection**: Monitor Rekor logs for unauthorized signatures
2. **Workflow Compromise**: Attacker modifies CI/CD
- **Mitigation**: Branch protection rules, required reviews
- **Detection**: Audit logs, signature mismatches
3. **Supply Chain Attack**: Compromised dependency
- **Mitigation**: SBOM verification, vulnerability scanning
- **Detection**: Trivy/Grype scans, GitHub security advisories
### Medium Risks
1. **Verification Failures**: False positives blocking releases
- **Mitigation**: Comprehensive testing, retry logic
- **Fallback**: Manual verification procedures
2. **Performance Impact**: Signing adds latency to builds
- **Mitigation**: Parallel execution, caching
- **Monitoring**: Track build times
### Low Risks
1. **Tool Updates**: Breaking changes in Cosign/SLSA
- **Mitigation**: Pin versions, test updates
- **Monitoring**: Renovate bot, release notes
---
## Success Metrics
### Quantitative Goals
- **100%** of Docker images signed within 4 weeks
- **100%** of release binaries signed within 4 weeks
- **≥95%** verification success rate
- **<5%** SBOM drift between builds
- **<30s** added to build time for signing
- **<10** false positive verification failures per month
### Qualitative Goals
- Developers can verify signatures locally
- Security team has visibility into supply chain
- Compliance requirements met (SOC2, SLSA)
- Zero supply chain incidents post-implementation
---
## Appendices
### Appendix A: Cosign Skill Implementation
#### A1: SKILL.md Specification
```markdown
---
name: "security-sign-cosign"
version: "1.0.0"
description: "Sign Docker images and artifacts with Cosign (Sigstore)"
author: "Charon Project"
license: "MIT"
tags: ["security", "signing", "cosign", "supply-chain"]
compatibility:
os: ["linux", "darwin"]
shells: ["bash"]
requirements:
- name: "cosign"
version: ">=2.4.0"
optional: false
environment_variables:
- name: "COSIGN_EXPERIMENTAL"
description: "Enable keyless signing"
default: "1"
required: false
parameters:
- name: "type"
type: "string"
description: "Artifact type (docker, file)"
default: "docker"
required: false
- name: "target"
type: "string"
description: "Image tag or file path"
required: true
---
# Security: Sign with Cosign
Sign Docker images and files using Cosign for supply chain security.
## Usage
```bash
# Sign Docker image
.github/skills/scripts/skill-runner.sh security-sign-cosign docker charon:local
# Sign file
.github/skills/scripts/skill-runner.sh security-sign-cosign file ./dist/charon-binary
```
```
#### A2: Execution Script Skeleton
```bash
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/../scripts/_logging_helpers.sh"
TYPE="${1:-docker}"
TARGET="${2:-}"
if [[ -z "${TARGET}" ]]; then
log_error "Usage: security-sign-cosign <type> <target>"
exit 1
fi
case "${TYPE}" in
docker)
log_step "COSIGN" "Signing Docker image: ${TARGET}"
cosign sign --yes "${TARGET}"
;;
file)
log_step "COSIGN" "Signing file: ${TARGET}"
cosign sign-blob --yes --output-signature="${TARGET}.sig" \
--output-certificate="${TARGET}.pem" "${TARGET}"
;;
*)
log_error "Invalid type: ${TYPE}"
exit 1
;;
esac
log_success "Signature created and stored in Rekor"
```
### Appendix B: SLSA Provenance Skill Implementation
#### B1: SKILL.md Specification
```markdown
---
name: "security-slsa-provenance"
version: "1.0.0"
description: "Generate and verify SLSA provenance attestations"
author: "Charon Project"
license: "MIT"
tags: ["security", "slsa", "provenance", "supply-chain"]
---
# Security: SLSA Provenance
Generate and verify SLSA provenance for build artifacts.
## Usage
```bash
# Generate provenance
.github/skills/scripts/skill-runner.sh security-slsa-provenance generate charon-binary
# Verify provenance
.github/skills/scripts/skill-runner.sh security-slsa-provenance verify charon-binary
```
```
### Appendix C: SBOM Verification Skill Implementation
#### C1: SKILL.md Specification
```markdown
---
name: "security-verify-sbom"
version: "1.0.0"
description: "Verify SBOM completeness and check for vulnerabilities"
author: "Charon Project"
license: "MIT"
tags: ["security", "sbom", "verification", "supply-chain"]
---
# Security: Verify SBOM
Verify Software Bill of Materials (SBOM) for Docker images and releases.
## Usage
```bash
# Verify Docker image SBOM
.github/skills/scripts/skill-runner.sh security-verify-sbom ghcr.io/user/charon:latest
# Verify local image
.github/skills/scripts/skill-runner.sh security-verify-sbom charon:local
```
```
---
## Conclusion
This implementation plan provides a comprehensive, phased approach to integrating supply chain security into Charon. By following this plan, the DevOps agent will:
1. **Sign all artifacts** with Cosign for tamper detection
2. **Generate SLSA provenance** for build transparency
3. **Verify SBOMs** for dependency tracking
4. **Enable local testing** via GitHub Skills
5. **Update processes** to include verification in DoD
**Estimated Effort**: 3-4 weeks (1 week per phase + testing)
**Complexity**: Medium (existing infrastructure, well-documented tools)
**Risk**: Low (non-breaking, incremental rollout)
**Ready for delegation to DevOps agent.**