Node images published by Midnight are:
- Attested using GitHub artifact attestations (build provenance)
- Accompanied by an SBOM (Software Bill of Materials) in SPDX-JSON format
- Scanned for vulnerabilities using Grype
GitHub artifact attestations use Sigstore under the hood but are fully managed by GitHub — no external Fulcio CA or Rekor transparency log dependencies. The attestation flow:
- GitHub Actions generates an OIDC token identifying the workflow
actions/attest-build-provenancecreates a SLSA build provenance attestation- The attestation is stored in GitHub's attestation API, linked to the image digest
- Consumers verify with
gh attestation verify, which checks the attestation against GitHub's API
SBOMs are generated using Syft in SPDX-JSON format:
- Scan: Syft analyzes the container image layers (file cataloger disabled to reduce size)
- Extract: Package information is extracted from package managers (apt, npm, cargo, etc.)
- Generate: An SPDX-JSON document is created listing all components
- Attest: The SBOM is attached to the image as an attestation using
actions/attest-sbom - Trim: SPDX relationships are stripped and JSON is minified to fit under the 16MB
actions/attest-sbompredicate limit (full SBOM preserved as build artifact) - Attest: The trimmed SBOM is attached to the image as an attestation using
actions/attest-sbom
GitHub's attestation API enforces a hard 16MB predicate size limit (actions/attest-sbom#168). The midnight-node image contains ~2,000 packages, producing SBOMs that exceed this limit. To fit:
- File cataloger disabled:
--select-catalogers '-file'excludes filesystem entries (~22MB to ~19MB) - Relationships stripped:
jq -c 'del(.relationships)'removes inter-package dependency edges and minifies JSON (~19MB to ~12MB)
The full unmodified SBOM is uploaded as a build artifact for detailed analysis. The attested SBOM retains all package identifiers, versions, licenses, and checksums — only relationship edges and JSON whitespace are removed.
Grype scans images against multiple vulnerability databases:
- National Vulnerability Database (NVD)
- GitHub Security Advisories
- OS-specific databases (Alpine, Debian, Ubuntu, etc.)
- Language-specific databases (npm, PyPI, RubyGems, Cargo, etc.)
Severity Threshold: Builds fail if any critical severity vulnerabilities are found.
The following images are attested and include SBOM attestations:
| Image | Registry | Description |
|---|---|---|
midnight-node |
ghcr.io/midnight-ntwrk/midnight-node |
Midnight blockchain node |
midnight-node |
midnightntwrk/midnight-node (Docker Hub) |
Midnight blockchain node |
midnight-node-toolkit |
ghcr.io/midnight-ntwrk/midnight-node-toolkit |
Transaction generator and testing tools |
midnight-node-toolkit |
midnightntwrk/midnight-node-toolkit (Docker Hub) |
Transaction generator and testing tools |
All images are published as multi-architecture manifests supporting:
linux/amd64(x86_64)linux/arm64(aarch64)
Both architecture variants are individually attested, and the manifest list itself is also attested.
| Workflow | Purpose |
|---|---|
.github/workflows/sbom-scan-image.yml |
Reusable workflow for SBOM generation, scanning, and attestation |
| Script | Purpose |
|---|---|
.github/scripts/sbom-scan.sh |
SBOM generation, trimming for attestation, and vulnerability scanning with retry logic |
Images must pass these checks before release:
- Build: Image builds successfully for all architectures
- Vulnerability Scan: No critical vulnerabilities detected
- Attestation: Build provenance attestation is created
- SBOM Attestation: SBOM is generated and attested to the image
For pull requests from forks, SBOM attestation is skipped because fork PRs don't have access to the OIDC token required for attestation. The vulnerability scan still runs to provide feedback.
Known vulnerabilities that cannot be immediately fixed can be temporarily ignored using .grype.yaml:
ignore:
# CVE-YYYY-XXXXX: Brief description
# Justification for ignoring
# Tracking: link to upstream issue
# TODO: Remove when fix is available
- vulnerability: CVE-YYYY-XXXXXEach ignore entry must include:
- Description of the vulnerability
- Justification for ignoring (risk assessment)
- Link to upstream tracking issue
- TODO comment with removal criteria
See Signing Runbook for procedures on managing CVE ignores.
- Verification Guide - How to verify image attestations and SBOMs
- Signing Runbook - Operational procedures