hardened-images: minimal, signed container images
Distroless, non-root OCI images built from Wolfi with apko and melange, with SBOMs, a blocking vulnerability scan, keyless signatures and SLSA L3 provenance, all built on GitHub Actions.
View on GitHub
hardened-images is a set of minimal, hardened OCI images built from Wolfi with apko and melange. The images have no package manager, run as non-root, and most ship no shell at all. Every build produces a software bill of materials, passes a blocking vulnerability scan, and is signed and attested, entirely on GitHub Actions.
The images
25 images are published to ghcr.io/blackshieldpt/<image>: nginx, nginx-acme, node, node24, node26, go, python, python-sodium, python315, python315-sodium, postgresql, valkey, minio, clickhouse, nats, openbao, openbao27, manticore, mailpit, redpanda, kafka, zookeeper, etcd, versitygw and static.
static is the odd one out: a 215 kB base holding a filesystem skeleton and a CA trust store and nothing else. It is the FROM line for a statically linked binary, such as a CGO_ENABLED=0 Go build or Rust against musl.
What each image guarantees
- Distroless and non-root: no apk, runs as UID 65532; the few images that need a shell because of upstream entrypoint scripts document it
- SBOM: CycloneDX and SPDX, attached as a cosign attestation
- Scanned: Grype and Trivy gate the build; exceptions are documented OpenVEX waivers, never a disabled scanner
- Signed (keyless): a cosign/Fulcio signature bound to the repository’s workflow identity, with no long-lived signing key
- SLSA build provenance (L3): generated by the GitHub Actions control plane and pushed to the registry
- Reproducible: apk-native images build from a committed apko lockfile with
SOURCE_DATE_EPOCHpinned to the source commit
Every image also has a -dev variant with a shell, apk and a small toolchain for debugging. Dev variants are signed and attested too, but their scan is advisory, so don’t run them in production.
Try it
Pin production to the immutable :<version>-<commit> tag or a digest, and verify the signature before you run it:
IMAGE=ghcr.io/blackshieldpt/nginx:1.31-<commit>
cosign verify "$IMAGE" \
--certificate-identity-regexp 'https://github.com/blackshieldpt/hardened-images/.github/workflows/.*' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com'
gh attestation verify "oci://$IMAGE" --owner blackshieldpt
See the README for verifying the SBOM and provenance attestations and for building images locally.
hardened-images is open source under the Apache 2.0 license.