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.

derived gcp emits CanModifyCode

match (effective permission)

{ "action": "artifactregistry.repositories.uploadArtifacts", "resource_type": "artifactregistry.googleapis.com/Repository" }

emit

source typeIdentity
target typeContainerRegistry
source<principal>
target<Artifact Registry repository>
permissionsartifactregistry.repositories.uploadArtifacts
conditionsiam_permission api_enabled
state logicACTIVE 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.'
move · open · esc close