This project demonstrates how to secure container images using:
- Syft for generating a Software Bill of Materials (SBOM)
- Cosign for signing and verifying image authenticity
- GitHub Actions for automating image scanning and signing
The goal is to give you a production-style setup for image trust and visibility — using an intentionally simple Flask app as the base.
- A Python Flask app containerized via Docker
- SBOM generated from the built image
- Container image signed with Cosign
- GitHub Actions pipeline that builds, scans, and signs on push
secure-sbom-supplychain/
├── app/
│ └── main.py # Flask application
├── Dockerfile # Defines the image
├── cosign.pub # Public key for signature verification
├── sbom.spdx.json # SBOM output (example/demo)
├── .github/
│ └── workflows/
│ └── supplychain.yml # CI: SBOM + Sign image
├── .gitignore
└── README.md
The app is served from a minimal Flask setup to simulate a deployable API. It's mounted in a Python 3.11 Docker container.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Secure SBOM Demo"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)FROM python:3.11-slim
WORKDIR /app
COPY app/ /app/
RUN pip install flask
EXPOSE 5000
CMD ["python", "main.py"]Install Syft:
docker build -t sbom-demo-app .
syft sbom-demo-app -o spdx-json > sbom.spdx.jsonInstall Cosign:
COSIGN_PASSWORD="" cosign generate-key-pair
cosign sign --key cosign.key sbom-demo-appOnly commit cosign.pub (public key).
cosign verify --key cosign.pub sbom-demo-appThe workflow automatically:
- Builds the Docker image
- Generates an SBOM with Syft
- Signs the image with Cosign (using a key stored as a GitHub secret)
env:
COSIGN_PASSWORD: ""
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}This project emulates modern supply chain security practices, including:
- Transparency of dependencies (SBOM)
- Artifact integrity (Cosign)
- CI-integrated trust policies
Paul D.
Security Automation Engineer
🔗 github.com/Paulinhx