Summary#
CI/CD artifact promotion에서 “스테이징에서 검증한 동일 artifact를 프로덕션으로 승격한다”는 보장이 깨지는 주요 원인은 mutable tag, digest 미고정, provenance/SBOM attestation 미검증, 배포 환경 drift이다. 특히 컨테이너 기반 파이프라인에서는 :latest, :prod, :staging 같은 태그가 재지정될 수 있기 때문에, 같은 태그를 배포해도 실제 실행되는 이미지 digest가 달라질 수 있다. 안전한 promotion 모델은 “빌드 1회 → immutable artifact 식별자 확보 → attest/SBOM 생성 → digest 기반 배포 → 환경별 policy 검증”에 가깝다.
핵심 원칙은 다음과 같다.
- artifact는 태그가 아니라 digest로 고정한다.
- 태그는 사람이 읽기 쉬운 alias로만 취급하고, 보안·재현성 경계에서는 신뢰하지 않는다.
- provenance attestation은 “누가, 어떤 소스와 빌드 정의로, 어떤 환경에서, 어떤 artifact를 만들었는가”를 검증하는 데 사용한다.
- SBOM은 artifact 내용 가시성을 제공하지만, 그 자체만으로 artifact 동일성이나 빌드 무결성을 보장하지 않는다.
- promotion은 재빌드가 아니라 이미 생성·검증된 artifact의 환경 이동이어야 한다.
- 환경별 설정 drift, base image drift, registry garbage collection, admission policy 차이는 promotion 실패 또는 “검증한 것과 다른 것 배포”로 이어질 수 있다.
Key Points#
1. Mutable tags are convenient but unsafe as promotion identifiers#
컨테이너 태그는 일반적으로 mutable하다. 예를 들어 myapp:staging이 오늘은 digest sha256:aaa...를 가리키고, 내일은 sha256:bbb...를 가리킬 수 있다. 이 상태에서 프로덕션 배포가 myapp:staging 또는 myapp:prod 같은 태그만 참조하면, 파이프라인 로그상으로는 동일한 태그를 사용했더라도 실제 artifact는 달라질 수 있다.
대표 failure modes:
- 스테이징 검증 후 같은 태그가 다른 이미지로 push됨
- rollback 시 이전 태그가 이미 새 digest를 가리킴
- 노드별 image cache 때문에 같은 tag라도 서로 다른 digest가 실행됨
imagePullPolicy설정과 registry 상태에 따라 실행 이미지가 달라짐latest또는 floating tag 사용으로 재현 가능한 incident 분석이 어려워짐
권장 패턴:
Bad:
image: registry.example.com/app:prod
Better:
image: registry.example.com/app@sha256:<digest>
Acceptable for readability if digest is still pinned:
image: registry.example.com/app:v1.2.3@sha256:<digest>
태그는 릴리스 노트, UI, 사람이 읽는 버전 구분에는 유용하지만, promotion의 security boundary에서는 digest가 기준이어야 한다.
2. Digest pinning makes the deployed artifact explicit#
OCI/container image digest는 content-addressed identifier이므로, 특정 manifest 또는 image content를 명확히 가리킨다. digest pinning을 사용하면 “프로덕션에 무엇이 배포되었는가”를 감사·재현·롤백할 수 있다.
효과:
- 스테이징에서 검증한 artifact와 프로덕션 artifact의 동일성 확인 가능
- incident 발생 시 어떤 digest가 실행되었는지 추적 가능
- rollback 대상이 태그가 아니라 정확한 digest가 됨
- admission controller나 policy engine이 digest 사용을 강제할 수 있음
- provenance, SBOM, signature를 특정 digest에 연결 가능
주의점:
- multi-arch image의 경우 image index digest와 platform-specific manifest digest를 구분해야 한다.
- digest를 고정해도 runtime config, secret, feature flag, database migration 상태가 다르면 결과는 달라질 수 있다.
- registry retention/garbage collection 정책이 잘못되면 과거 digest rollback이 불가능할 수 있다.
3. Promotion should move artifacts, not rebuild them#
안전한 promotion은 보통 다음 흐름을 따른다.
Source commit
→ build once
→ produce artifact digest
→ sign artifact / create provenance
→ create SBOM
→ deploy digest to dev/staging
→ verify tests and policies
→ promote same digest to production
반대로 각 환경마다 다시 빌드하면 다음 문제가 생긴다.
- base image가 변경되어 다른 결과물이 생성됨
- dependency resolver가 새 버전을 선택함
- build cache 차이로 artifact가 달라짐
- 빌드 환경의 compiler/toolchain 차이가 결과에 반영됨
- “스테이징에서 검증한 artifact”와 “프로덕션에 배포한 artifact”가 불일치함
따라서 promotion은 “환경마다 새 빌드”가 아니라 “동일 digest를 환경별 배포 설정으로 이동”하는 형태가 바람직하다.
4. Provenance attestations address build integrity, not runtime correctness#
SLSA provenance나 in-toto attestation은 artifact가 어떤 소스, 빌드 정의, builder, parameters로 생성되었는지를 설명하고 검증 가능하게 만든다. 이는 다음 질문에 답하는 데 도움이 된다.
- 이 artifact는 신뢰된 CI/CD 시스템에서 만들어졌는가?
- 어떤 repository와 commit에서 만들어졌는가?
- 어떤 workflow/build definition을 사용했는가?
- 빌드 중 사용된 parameters나 materials는 무엇인가?
- attestation이 해당 artifact digest에 묶여 있는가?
하지만 provenance attestation은 다음을 자동으로 보장하지 않는다.
- 애플리케이션이 버그 없이 동작한다.
- 프로덕션 환경 설정이 스테이징과 동일하다.
- 배포 후 runtime이 변조되지 않았다.
- secret, database, feature flag, external dependency가 안전하다.
- SBOM에 있는 모든 취약점이 해결되었다.
즉, provenance는 build supply chain integrity의 근거이지, 운영 환경 전체의 correctness 증명은 아니다.
5. SBOM and attestation must be bound to the artifact digest#
SBOM 또는 provenance가 존재하더라도, 그것이 배포된 artifact와 정확히 연결되지 않으면 promotion 보장에 실패한다.
Failure modes:
- SBOM은
app:v1.2.3에 대해 생성되었지만 태그가 나중에 다른 digest를 가리킴 - attestation은 빌드 artifact digest가 아니라 release tag에만 연결됨
- registry 복사 또는 mirroring 과정에서 manifest digest가 달라짐
- multi-arch manifest 중 특정 architecture에 대한 attestation이 누락됨
- admission 단계에서 signature는 확인하지만 provenance predicate 내용은 확인하지 않음
권장 검증:
- 배포 manifest의 image digest와 attestation subject digest가 일치하는지 확인
- builder identity, source repository, branch/tag policy, workflow identity를 확인
- SBOM subject가 실제 배포 digest와 연결되는지 확인
- production admission policy에서 unsigned 또는 unpinned image를 거부
- provenance/SBOM 생성 여부뿐 아니라 내용 정책을 검증
6. Environment drift can defeat otherwise correct artifact promotion#
digest pinning과 attestation이 있어도 환경 drift가 크면 스테이징 검증 결과가 프로덕션에서 재현되지 않는다.
주요 drift 항목:
- Kubernetes version, admission controller, runtime class 차이
- node OS, kernel, container runtime, CPU architecture 차이
- config map, secret, environment variable 차이
- feature flag, traffic routing, service mesh policy 차이
- database schema 또는 migration 적용 상태 차이
- external service endpoint, IAM permission, network policy 차이
- image pull policy와 registry mirror 설정 차이
- Helm/Kustomize overlay 차이
- resource limit, autoscaling, pod disruption budget 차이
운영적으로는 artifact promotion과 environment promotion을 분리해서 보아야 한다. artifact 동일성은 digest와 attestation으로 관리하고, 환경 drift는 GitOps, policy-as-code, conformance checks, deployment diff, progressive delivery telemetry로 관리하는 것이 적절하다.
7. Common failure scenarios#
Scenario A — Retagging after staging approval
1. app:staging → sha256:111
2. staging tests pass
3. new build pushes app:staging → sha256:222
4. production deploy uses app:staging
5. production runs untested sha256:222
Mitigation:
- staging approval record에 digest 저장
- production deploy는 approved digest만 사용
- mutable promotion tag를 production input으로 사용하지 않음
Scenario B — Rollback to a tag that no longer means the old image
1. app:v1.2.3 initially points to sha256:aaa
2. incident occurs after app:v1.2.4
3. operator rolls back to app:v1.2.3
4. tag was overwritten and now points to sha256:ccc
Mitigation:
- rollback catalog는 digest 기반으로 보관
- registry tag immutability 활성화
- release metadata에 digest, signature, SBOM, provenance references 저장
Scenario C — Signed image but weak policy
1. Image is signed
2. Admission controller verifies only signature existence
3. It does not verify source repo, builder, branch, or workflow
4. Attacker signs image from untrusted build path
Mitigation:
- signature verification과 provenance predicate policy를 함께 적용
- trusted builder identity와 source repository allowlist 사용
- SLSA/in-toto subject digest 확인
Scenario D — Same digest, different runtime behavior
1. Same image digest deployed to staging and production
2. Production has different feature flag and database schema
3. Application fails only in production
Mitigation:
- environment diff checks
- schema migration gates
- configuration provenance 또는 config versioning
- progressive rollout and automated rollback
8. Practical guardrails#
Recommended controls:
- CI에서 image digest를 build output으로 기록
- CD는 tag가 아니라 digest를 입력으로 받음
- registry tag immutability 활성화
latest사용 금지 또는 production 금지- Kubernetes admission policy로 digest pinning 강제
- Sigstore/cosign 등으로 image signing 및 attestation 검증
- SLSA provenance 또는 in-toto attestation 생성
- SBOM을 artifact digest에 연결
- release metadata store에 commit, digest, SBOM, provenance, test result, approval 기록
- staging과 production의 config diff를 배포 전 확인
- rollback 대상 digest를 retention policy로 보존
- multi-arch image의 digest/attestation coverage 확인
- promotion pipeline에서 “rebuild” 단계 제거
Example policy intent:
Allow production deployment only if:
- image is referenced by digest
- digest has valid signature
- provenance subject matches digest
- builder identity is trusted
- source repository is approved
- commit or release ref satisfies policy
- SBOM exists for the same digest
- environment diff is within approved bounds
Cautions#
- 이 초안은 공개적으로 알려진 CI/CD, container supply chain, SLSA, in-toto, Kubernetes, Docker 문서의 일반 원칙을 바탕으로 작성되었다.
- 현재 실행 환경에는 사용자가 명시한
WebSearch/WebFetch도구가 제공되지 않아, 실시간 검색 결과 검증은 수행하지 못했다. 아래 URL은 안정적인 공개 문서로 선별했지만, 게시 전 최신 내용 확인이 필요하다. - “digest pinning”은 artifact 동일성을 강화하지만, 런타임 설정·데이터베이스·네트워크·권한·feature flag 차이까지 해결하지는 않는다.
- provenance attestation은 build integrity의 근거이지, 취약점 부재나 runtime safety의 증명은 아니다.
- SBOM은 구성요소 가시성을 제공하지만, SBOM 존재만으로 artifact가 안전하거나 검증되었다고 볼 수 없다.
- container image digest는 manifest/index 수준에서 다뤄지므로 multi-platform image에서는 어떤 digest를 정책 대상으로 삼는지 명확히 해야 한다.
- registry mirroring, image signing, attestation storage 방식에 따라 digest와 metadata 연결 방식이 달라질 수 있다.
- 조직별 threat model에 따라 필요한 통제 수준은 다르다. 예를 들어 내부 서비스 배포와 regulated production 배포는 provenance policy 강도가 달라야 한다.
Sources#
- https://docs.docker.com/reference/cli/docker/image/pull/
- https://docs.docker.com/build/metadata/attestations/
- https://kubernetes.io/docs/concepts/containers/images/
- https://slsa.dev/spec/v1.0/provenance
- https://slsa.dev/spec/v1.0/requirements
- https://github.com/in-toto/attestation
- https://docs.sigstore.dev/cosign/signing/overview/
- https://docs.sigstore.dev/cosign/verifying/verify/
Related#
- self-heal safety
- Resize Coordinate Drift, and Semantic Restore Invariants
- ArgoCD GitOps Failure Modes: Sync Waves, Hooks, Health Checks, Diff Customization, and ApplicationSet Drift Boundaries
Sagwan Revalidation 2026-07-21T14:16:53Z#
- verdict:
ok - note: digest 고정·attestation 검증 중심 권장안은 현재도 유효함