Hardening the Build Pipeline
Everything in this course has added checks to Tiffin's pipeline. But the pipeline is also a target: it holds deploy credentials, it can push images, and whatever it builds goes straight to production. An attacker who controls the pipeline does not need to break the app. This final lesson turns the pipeline itself into something worth trusting.
The rule
Treat the pipeline as production: guard its inputs, its powers and its outputs.
Guard its inputs
- Protected branches: nobody pushes to
maindirectly; changes need a review by someone other than the author. - Code owners for the pipeline file itself, so only the platform team can approve changes to it.
- Pin third-party plugins by full commit hash, not a movable tag, and remove plugins you no longer use.
- Untrusted pull requests (from forks or outside contributors) run with no secrets and need approval.
Guard its powers
- Ephemeral runners: a fresh machine per job, so one job cannot leave a backdoor for the next.
- Short-lived credentials per job (OIDC), each with a least-privilege role scoped to one environment.
- Default pipeline tokens set to read-only, raised only in jobs that need more.
Guard its outputs
- Scan, generate an SBOM, and sign the image with provenance.
- The cluster verifies the signature before running anything.
- Keep audit logs of who changed the pipeline, who approved deploys, and what ran.
permissions: { contents: read } # read-only by default
jobs:
build:
runs-on: ephemeral
permissions: { id-token: write, contents: read }
steps:
- uses: vendor/checkout@8f4b7f84bd579b95d7f0b90f8d8b6e5d9b8a5c1e # pinned by hash
- run: build-image tiffin && image-scan tiffin --fail-on new:high
- run: sbom tiffin > tiffin.cdx.json && sign tiffin --provenance --key kms://tiffin-signing
deploy-production:
needs: [build, dast-staging]
environment: production # requires approvalThe shortcut
Picture an attacker who wants to reach production without touching the app, and walk the three gates: Can they change what goes in? Can they borrow the pipeline's powers? Can they swap what comes out?
Change what goes in
Push to
main? Protected. Edit the pipeline file? Needs a code owner. Poison a plugin tag? Plugins are pinned by hash.
Drills
Answer fast — trust the rule.
Why pin a third-party pipeline plugin by commit hash rather than a version tag?
What is the main benefit of ephemeral runners?
A pull request from an unknown fork triggers the pipeline. What should it get?
A stolen registry password is used to push an unsigned image named tiffin. What stops it running?
Every Tiffin job gets a default pipeline token that can write to the repository. Which gate is weak, and what is the fix?
Remember
- Treat the pipeline as production: guard its inputs, its powers and its outputs.
- Walk the gates: change what goes in? borrow its powers? swap what comes out?
- Pinned plugins, fork builds without secrets, ephemeral runners, short-lived roles, signed and verified images.
