Command Palette

Search for a command to run...

Hectal
← All projects

Project 11 of 12 · project brief

A DevSecOps Pipeline: Scan, SBOM, Sign, Verify

SAST, dependency and secret scanning, image scanning, SBOM generation, keyless image signing, and cluster-side signature verification, without slowing developers down.

Advanced 3 days 4 milestones

The scenario

A customer security questionnaire asks: 'How do you know the image running in production is the one your pipeline built, and what's inside it?'. Today the honest answer is 'we don't'. Your brief: a pipeline that finds problems early, produces an SBOM for every image, signs images, and a cluster that refuses unsigned images.

Before you start

Stack

GitHub ActionsSemgrep / CodeQL (SAST)Dependency scanning (OWASP Dependency-Check / Trivy fs / Dependabot)GitleaksTrivySyft (SBOM)Cosign (keyless, Sigstore)Kyverno verifyImages

Target architecture

Project 11 architecturediagram
Rendering diagram…

Deliverables and requirements

You will hand in

  • A reusable workflow with secret, SAST, dependency, and image scanning, plus quality gates
  • SBOM (SPDX or CycloneDX) generated and attached to every image as an attestation
  • Keyless Cosign signatures tied to the workflow's identity
  • A Kyverno policy that blocks unsigned images or images not signed by your pipeline

Functional

  • PRs show findings inline; critical findings block merge
  • Every pushed image has a signature and SBOM attestation
  • Deploying an unsigned image to prod namespaces is rejected

Non-functional

  • Full security stages add < 4 minutes to the pipeline (parallel jobs, caching)
  • Findings deduplicated and triaged (suppressions with expiry and justification)
  • No long-lived signing keys (keyless via OIDC)

Milestones

  1. 1

    Shift-left scanning

    Done when: Secrets, code, and dependency issues caught in PRs.

    • Gitleaks pre-commit hook and CI job
    • Semgrep or CodeQL on PRs with SARIF upload to code scanning
    • Dependency scanning with a fail threshold on critical, and Dependabot/Renovate for updates

    Prove it works

    terminal
    $ # PR checks
    ── expected output ──
    ✓ secrets (gitleaks)
    ✗ sast (semgrep) — 1 blocking: java.lang.security.audit.sqli.jdbc-sqli
    ✓ dependencies (0 critical, 3 high → tickets)
  2. 2

    Image scanning and SBOM

    Done when: Every image scanned and described.

    • Trivy image scan with --exit-code 1 --severity CRITICAL --ignore-unfixed
    • Syft to generate an SPDX SBOM
    • Store the SBOM as an attestation (cosign attest --type spdxjson)

    Prove it works

    terminal
    $ syft ghcr.io/<you>/shoplite-api:sha-3f2a1c9 -o table | head -4
    ── expected output ──
    NAME VERSION TYPE
    spring-boot 3.5.6 java-archive
    jackson-databind 2.19.2 java-archive
    libc6 2.39-0 deb
  3. 3

    Keyless signing

    Done when: Images signed by the workflow's OIDC identity.

    • permissions: id-token: write in the workflow
    • cosign sign --yes <image>@<digest> (sign by digest, not tag)
    • Verify locally with --certificate-identity and --certificate-oidc-issuer

    Prove it works

    terminal
    $ cosign verify ghcr.io/<you>/shoplite-api@sha256:9b1f... --certificate-identity-regexp 'https://github.com/<you>/shoplite-api/.github/workflows/release.yml@refs/heads/main' --certificate-oidc-issuer https://token.actions.githubusercontent.com | jq -r '.[0].critical.image."docker-manifest-digest"'
    ── expected output ──
    sha256:9b1f...
  4. 4

    Verify in the cluster

    Done when: Kyverno blocks images not signed by your pipeline.

    • Kyverno verifyImages rule with keyless attestor (subject regexp + issuer) for prod namespaces
    • Start in Audit, then Enforce (Platform course, Mission 0.4)
    • Test with an unsigned image

    Prove it works

    terminal
    $ kubectl -n shoplite-prod run test --image=ghcr.io/<you>/unsigned:1.0
    ── expected output ──
    Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request: ... verify-signature: failed to verify image ghcr.io/<you>/unsigned:1.0: no matching signatures

Would you run this in production?

  • ☐Secrets scanning before code leaves the laptop and again in CI
  • ☐Findings triaged with owners and SLAs; suppressions expire
  • ☐Images referenced by digest; SBOMs stored and queryable
  • ☐Signature verification enforced at admission
  • ☐Least-privilege CI tokens; third-party actions pinned by SHA

Stretch goals

  • SLSA provenance attestations (actions/attest-build-provenance)
  • Continuous SBOM-based vulnerability monitoring (Dependency-Track)
  • DAST (OWASP ZAP baseline) against a preview environment

Show it off

Résumé bullet

Built a DevSecOps pipeline with secret, SAST, dependency, and image scanning, SBOM attestations, keyless Cosign signing, and Kyverno admission-time signature verification, adding under 4 minutes to builds.

Demo script

  • A PR blocked by a SAST finding
  • Query the SBOM for a vulnerable library across images
  • Deploy an unsigned image and show the rejection

Interview questions about this project

01

What is an SBOM and why does it matter?

02

How does keyless signing work?