Lesson 05 Security Scanning & Image Signing
Theme:
Lesson 05 · Slide 1

Lesson 05 — Security Scanning & Image Signing

Trivy, SBOMs, cosign, and branch protection — turning the green check into a contract.

Cloud & DevOps Module 2

Lesson 05 · Slide 2

What L04 did NOT cover

Lesson 05 · Slide 3

The supply-chain threat model

Things you depend on

  • Base images (python:3.11-slim)
  • pip / npm packages
  • Transitive dependencies
  • OS packages in the image

Things that touch your image

  • Container registry
  • CI runner environment
  • Deploy target
  • CD pipeline steps

Each touch point is a possible compromise vector — even if your code is clean.

Lesson 05 · Slide 4

Vulnerability scanning with Trivy

- name: Trivy scan
  uses: aquasecurity/trivy-action@0.24.0
  with:
    image-ref: api:ci-${{ github.sha }}
    severity: HIGH,CRITICAL
    exit-code: 1
    ignore-unfixed: true
Lesson 05 · Slide 5

Trivy vs Grype

ToolVendorAdvisory DBNotes
Trivy Aqua Security (OSS) Broader multi-source DB Faster, GitHub Action available, scans config/secrets too
Grype Anchore (OSS) Grype DB + GHSA Pairs naturally with Syft for SBOM-first workflows

Either works. Pick one and stick to it — mixing tools leads to inconsistent severity noise. We use Trivy in this sample.

Lesson 05 · Slide 6

SBOM: what and why

A Software Bill of Materials (SBOM) lists every package that ended up in your image — the full dependency tree, not just your direct deps.

Lesson 05 · Slide 7

Generating an SBOM with Syft

- name: Generate SBOM
  uses: anchore/sbom-action@v0
  with:
    image: api:ci-${{ github.sha }}
    format: spdx-json
    output-file: sbom-api.spdx.json
- uses: actions/upload-artifact@v4
  with: { name: sbom-api, path: sbom-api.spdx.json }
Lesson 05 · Slide 8

Image signing with cosign

cosign signs an image (or any OCI artifact) with a key. The signature lives in the registry next to the image. Verifiers check the signature before deploying.

Two signing modes:

The signature attests: “this image was produced by the expected pipeline at the expected commit.”

Lesson 05 · Slide 9

Keyless signing in GitHub Actions

- uses: sigstore/cosign-installer@v3
- name: Sign image (keyless)
  env:
    COSIGN_EXPERIMENTAL: "true"
  run: |
    cosign sign --yes \
      ghcr.io/${{ github.repository }}/api@${{ steps.build.outputs.digest }}
Lesson 05 · Slide 10

Verifying signatures at deploy time

cosign verify \
  --certificate-identity-regexp "https://github.com/$ORG/$REPO/.*" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/$ORG/$REPO/api@$DIGEST

Deploy-side verification checks that the image came from the expected pipeline — not just that it has a valid signature, but that the cert identity pins it to your workflow.

Run this in a Kubernetes admission webhook or a deploy job to prevent unsigned images from reaching production.

Lesson 05 · Slide 11

Branch protection

GitHub UI: Settings → Branches → Add branch protection rule → pattern main

The green check is now a contract: merging without it is impossible.

Lesson 05 · Slide 12

What we’ll add in the lab

By the end: CVE gates on PRs, signed images on main, verified trust chain.

Lesson 05 · Slide 13

Common gotchas

Lesson 05 · Slide 14

Recap & what’s next

Coming up: Lesson 06 — push to GHCR/ECR and deploy.