If ECS or Lambda will run whatever tag floated into ECR, a compromised CI job or confused-deputy push can ship malware. SLSA provenance attestations bind an image digest to the build system, source commit, and builder identity—so deploy hooks can refuse unsigned or mismatched artifacts.
⚡ TL;DR: Build Node images in hermetic CI, sign with Sigstore/Cosign, attach SLSA provenance, verify digest + attestation in CD before ECS/Lambda update. Block mutable
:latest. Pair with Lambda Code Signing, Policy-as-Code for AI, and Agent Tool Allowlists.
Threat model in one line
Attacker pushes evil:latest to ECR
OR steals CI OIDC to build from a fork
Without verify: ECS rolls out evil
With SLSA gate: digest lacks trusted provenance → deploy fails closed
Build, attest, push
# GitHub Actions sketch
- uses: docker/build-push-action@v6
with:
push: true
tags: ${{ env.ECR }}/checkout:${{ github.sha }}
provenance: true
sbom: true
- name: Cosign sign
run: |
cosign sign --yes ${{ env.ECR }}/checkout@${{ steps.build.outputs.digest }}
cosign attest --yes --predicate slsa-provenance.json \
${{ env.ECR }}/checkout@${{ steps.build.outputs.digest }}
# Node image: reproducible-ish defaults
FROM public.ecr.aws/docker/library/node:22-bookworm-slim@sha256:...
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY dist ./dist
USER node
CMD ["node", "dist/server.js"]
Pin base digests. Avoid npm install without lockfiles. Treat AI-generated Dockerfiles with the same gates as humans.
Verify before deploy
# CD gate
DIGEST=$(aws ecr describe-images --repository-name checkout \
--image-ids imageTag=$GIT_SHA --query 'imageDetails[0].imageDigest' --output text)
cosign verify --certificate-identity-regexp '.*github.com/acme/checkout.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"$ECR/checkout@$DIGEST"
cosign verify-attestation --type slsaprovenance \
"$ECR/checkout@$DIGEST" | jq -e '.payload' >/dev/null
# only then:
aws ecs update-service --force-new-deployment ...
# or Lambda package / container image URI with that digest
# OPA/Conftest: deny mutable tags
deny[msg] {
input.image.tag == "latest"
msg := "mutable tag latest forbidden"
}
deny[msg] {
not input.provenance.verified
msg := "missing verified SLSA provenance"
}
For zip-based Lambda, use code signing configs—see Lambda Code Signing. Same policy spirit: only CI-built, attested artifacts reach prod.
Closing checklist
- [ ] Images tagged by git SHA / digest only;
:latestdenied - [ ] Cosign signatures + SLSA attestations produced in CI
- [ ] CD verifies signature and provenance before ECS/Lambda update
- [ ] Base images pinned by digest
- [ ] ECR scan-on-push + admission policy for critical CVEs
- [ ] Break-glass unsigned deploys require dual-control and expire
Related reading
- Lambda Code Signing: Enforce CI-Built Artifacts in Every Account
- Policy-as-Code for AI: OPA Checks Before Every Shell Execution
- Agent Tool Allowlists: Least Privilege for Filesystem and Shell Access
- Lambda Multi-Arch Builds: arm64 CI Matrices That Actually Ship
Last updated on September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
