This guide explains how the CyberChef MCP Server implements supply chain attestations to achieve optimal Docker Scout health scores on Docker Hub.
Docker Scout health scores provide security grading (A-F) for container images on Docker Hub only. Images on other registries (GHCR, ECR, ACR, etc.) can be scanned with Docker Scout but do not receive letter-grade health scores.
Supply Chain Attestations account for 15 points out of 100 in the health score calculation - one of the highest-weighted policy categories. Missing attestations can drop a score from A to C grade or worse.
Docker Scout requires both of the following attestations for optimal health scores:
- SBOM (Software Bill of Materials) - Documents all software packages and dependencies in the image
- Provenance (Build Attestation) - Records build details, source repository, and build environment
Images lacking either attestation are marked as non-compliant with the "Supply Chain Attestations" policy.
The mcp-release.yml workflow implements dual-registry publishing with attestations:
# Push to both GHCR (for GitHub ecosystem) and Docker Hub (for health scores)
tags: |
${{ steps.meta-ghcr.outputs.tags }}
${{ steps.meta-dockerhub.outputs.tags }}provenance: mode=max # Max-level provenance for SLSA Build Level 3 compliance
sbom: true # Generate and attach SBOM attestation (in-toto SPDX format)Key Configuration Details:
provenance: mode=max: Generates maximum-detail provenance attestations compliant with SLSA Build Level 3- Public repos:
mode=maxis default - Private repos:
mode=minis default (must override tomode=maxfor best scores)
- Public repos:
sbom: true: Generates SBOM attestations using Syft in SPDX-JSON format- Automatic Attachment: Attestations are automatically pushed with the image to both registries
permissions:
contents: write
packages: write
security-events: write
attestations: write # Required for attestation generation
id-token: write # Required for OIDC token generation (attestation signing)The attestations: write and id-token: write permissions enable GitHub Actions to generate and sign attestations using OIDC tokens.
The project uses a two-pronged approach to SBOMs:
-
Docker Attestation SBOM (in-toto format, attached to image manifest)
- Purpose: Docker Scout health scores,
docker sbomcommand, registry verification - Format: SPDX-JSON
- Generator: Syft (via BuildKit)
- Location: Attached to image in registry
- Purpose: Docker Scout health scores,
-
Trivy SBOM Artifact (standalone file, released as asset)
- Purpose: Offline audits, third-party tools, compliance documentation
- Format: CycloneDX JSON
- Generator: Trivy
- Location: GitHub Release assets
This dual strategy ensures both automated registry-based validation and manual/offline verification capabilities.
Configure these secrets in your GitHub repository settings (Settings → Secrets and variables → Actions):
| Secret Name | Description | How to Obtain |
|---|---|---|
DOCKERHUB_USERNAME |
Your Docker Hub username | Your Docker Hub account username |
DOCKERHUB_TOKEN |
Docker Hub access token | Create token with "Read, Write, Delete" scope |
Creating a Docker Hub Access Token:
- Log in to Docker Hub
- Navigate to Account Settings → Security
- Click "New Access Token"
- Name it (e.g., "GitHub Actions - CyberChef MCP")
- Select "Read, Write, Delete" permissions
- Click "Generate" and copy the token
- Add to GitHub repository secrets as
DOCKERHUB_TOKEN
- Create a repository on Docker Hub (e.g.,
yourusername/cyberchef-mcp) - Enable Docker Scout (automatically enabled for all repositories)
- Configure the workflow environment variable:
env:
DOCKERHUB_IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/cyberchef-mcpNote: The workflow automatically constructs the image name using DOCKERHUB_USERNAME to avoid hardcoding usernames.
After a release, verify that attestations are attached to your Docker Hub image:
# Pull the image
docker pull yourusername/cyberchef-mcp:latest
# Inspect SBOM attestation
docker sbom yourusername/cyberchef-mcp:latest
# Inspect provenance attestation (requires Docker Buildx)
docker buildx imagetools inspect yourusername/cyberchef-mcp:latest --format '{{ json .Provenance }}'Scan the image and check policy compliance:
# Check health score policies
docker scout quickview yourusername/cyberchef-mcp:latest
# Detailed policy evaluation
docker scout cves yourusername/cyberchef-mcp:latest --only-policy
# Check specifically for supply chain attestations
docker scout policy yourusername/cyberchef-mcp:latestExpected output for compliant images:
✓ Supply chain attestations [15/15 points]
- SBOM attestation: Present
- Provenance attestation: Present (mode=max)
- Go to your Docker Hub repository:
https://hub.docker.com/r/yourusername/cyberchef-mcp - Click the "Tags" tab
- Select your tag (e.g.,
latest,1.5.0) - View the health score badge (A-F grade)
- Click "View policy results" to see detailed scoring
The Chainguard distroless base image includes SLSA Build Level 3 provenance. Verify it's preserved:
# Inspect the base image provenance
docker buildx imagetools inspect cgr.dev/chainguard/node:latest --format '{{ json .Provenance }}'
# Compare with our final image provenance
docker buildx imagetools inspect yourusername/cyberchef-mcp:latest --format '{{ json .Provenance }}'The final image provenance should include build information but won't directly "inherit" the base image provenance (each build generates its own provenance attestation).
Symptoms:
- Docker Hub Scout shows "C" grade
- Policy evaluation shows: ❌ Supply Chain Attestations [0/15 points]
Solution:
- Verify the workflow used
docker/build-push-action@v6or later - Confirm
provenance: mode=maxandsbom: trueare set - Ensure
push: trueis set (attestations don't work withload: true) - Check GitHub Actions permissions include
attestations: writeandid-token: write - Verify the image was pushed to Docker Hub (not just GHCR)
Cause: Using load: true instead of push: true
Solution: Attestations require pushing to a registry. For local testing, use the mcp-docker-build.yml workflow which loads images locally (without attestations). The mcp-release.yml workflow handles attestations for releases.
Cause: Private repositories default to provenance: mode=min
Solution: Explicitly set provenance: mode=max in your workflow (already configured in mcp-release.yml).
Possible Causes:
- Base image uses distroless/scratch with no package manager metadata
- Dependencies installed outside package manager tracking
- Multi-stage build removed package metadata
Mitigation:
- Chainguard images include comprehensive metadata
- Use BuildKit's
--sbom-scan-contextto scan build context - Keep package metadata in final image layer
-
Always Push to Registry: Attestations only work when pushing to a registry (Docker Hub, GHCR, etc.), not when using
load: true -
Use mode=max Provenance: For best health scores, always use
provenance: mode=max, especially for private repositories -
Verify After Each Release: Check health scores and attestations after each release to catch issues early
-
Monitor Scout Policies: Docker Scout policies evolve - regularly review policy changes that might affect your score
-
Document Base Image Choices: Note why you chose specific base images (e.g., Chainguard for zero CVEs and SLSA Level 3 provenance)
-
Test Locally Without Attestations: Use separate workflows for local testing (with
load: true) and releases (withpush: trueand attestations)
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Actions Workflow │
│ (mcp-release.yml) │
└───────────┬─────────────────────────────────────┬───────────────┘
│ │
│ docker/build-push-action@v6 │
│ - provenance: mode=max │
│ - sbom: true │
│ - push: true │
│ │
v v
┌────────────────────────────┐ ┌────────────────────────────┐
│ GitHub Container Registry │ │ Docker Hub │
│ (ghcr.io) │ │ (docker.io) │
│ │ │ │
│ doublegate/cyberchef-mcp │ │ username/cyberchef-mcp │
│ │ │ │
│ ✓ Image │ │ ✓ Image │
│ ✓ SBOM attestation │ │ ✓ SBOM attestation │
│ ✓ Provenance attestation │ │ ✓ Provenance attestation │
│ ❌ Health score (N/A) │ │ ✓ Health score (A-F) │
└────────────────────────────┘ └────────────────────────────┘
│
│
┌────────────v───────────────┐
│ Docker Scout Analyzer │
│ │
│ - Evaluates SBOM │
│ - Validates provenance │
│ - Scans vulnerabilities │
│ - Calculates health score │
│ │
│ Grade: A (85-100 points) │
│ ✓ Supply Chain: 15/15 │
└────────────────────────────┘
- Docker Scout Policy Requirements
- Docker Scout Health Scores
- GitHub Actions Attestations
- SLSA Build Levels
- Chainguard Images Documentation
- Syft SBOM Generator
- Initial implementation of dual-registry push (GHCR + Docker Hub)
- Added
provenance: mode=maxandsbom: trueattestation configuration - Documented setup, verification, and troubleshooting procedures
- Resolved "C" grade issue by enabling Docker Hub push with attestations