gcp-gke-registry-push
artifactregistry.repositories.uploadArtifacts on an Artifact Registry repository (or storage.objects.create on a legacy GCR bucket) lets an attacker push/overwrite an image tag that GKE workloads pull - registry-level CanModifyCode, propagated by container-chains to each consuming workload.
match (effective permission)
{
"action": "artifactregistry.repositories.uploadArtifacts",
"resource_type": "artifactregistry.googleapis.com/Repository"
}
emit
| source type | Identity |
|---|---|
| target type | ContainerRegistry |
| source | <principal> |
| target | <Artifact Registry repository> |
| permissions | artifactregistry.repositories.uploadArtifacts |
| conditions | iam_permission api_enabled |
| state logic | ACTIVE if artifactregistry.repositories.uploadArtifacts is confirmed effective on the repository. BLOCKED if the repository is configured with virtual-repository immutability (tag immutability) — overwriting a tag is rejected and the supply-chain fan-out is blocked for tag-referenced consumers. container-chains image-push-poisons-consumers then handles per-consumer propagation (gating on mutable vs. digest-pinned references). |
Narrative
{principal.name} can push or overwrite images in Artifact Registry repository {registry.name} (artifactregistry.repositories.uploadArtifacts); container-chains propagates this CanModifyCode to every GKE workload that references a mutable tag from that repository, executing attacker code as each workload's identity.
Raw rule rules/derived/gcp/gke.yaml
id: gcp-gke-registry-push
emits: CanModifyCode
description: "artifactregistry.repositories.uploadArtifacts on an Artifact Registry repository (or storage.objects.create\
\ on a legacy GCR bucket) lets an attacker push/overwrite an image tag that GKE workloads pull \u2014\
\ registry-level CanModifyCode, propagated by container-chains to each consuming workload."
match_effective_permission:
action: artifactregistry.repositories.uploadArtifacts
resource_type: artifactregistry.googleapis.com/Repository
emit:
source_type: Identity
target_type: ContainerRegistry
source: <principal>
target: <Artifact Registry repository>
permissions:
- artifactregistry.repositories.uploadArtifacts
conditions:
- iam_permission
- api_enabled
state_logic: "ACTIVE if artifactregistry.repositories.uploadArtifacts is confirmed effective on the\
\ repository. BLOCKED if the repository is configured with virtual-repository immutability (tag immutability)\
\ \u2014 overwriting a tag is rejected and the supply-chain fan-out is blocked for tag-referenced\
\ consumers. container-chains image-push-poisons-consumers then handles per-consumer propagation (gating\
\ on mutable vs. digest-pinned references)."
confidence: 0.95
derived_from:
- '<effective iam_permission: artifactregistry.repositories.uploadArtifacts>'
false_positive_note: "Propagation to consumers is handled by container-chains (image-push-poisons- consumers)\
\ \u2014 do NOT re-derive the fan-out here. The tag-immutability check on the repository is the primary\
\ BLOCKED gate; per-consumer digest pinning is container-chains' gate. Also covers the legacy GCR\
\ path via storage.objects.create on the underlying GCS bucket (gcr.io/<project>/...), but that path\
\ requires storage bucket access and is rarer."
narrative: '{principal.name} can push or overwrite images in Artifact Registry repository {registry.name}
(artifactregistry.repositories.uploadArtifacts); container-chains propagates this CanModifyCode to
every GKE workload that references a mutable tag from that repository, executing attacker code as
each workload''s identity.'