gcp-ar-wif-writer-trust

An Artifact Registry repo IAM binding for a Workload Identity Federation principalSet/principal with uploadArtifacts grants an external OIDC identity (e.g. GitHub Actions) direct push access - supply-chain from external CI into GCP workloads.

derived gcp emits TrustsExternalIdentity

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'repo': None} HasPolicy {'repo_policy': None}

where

?repo_policy is a ResourcePolicy of an Artifact Registry repository ?repo ?repo_policy has an IAM binding for a WIF principal (member starts with principalSet://iam.googleapis.com/ or principal://iam.googleapis.com/) the binding role or permissions include artifactregistry.repositories.uploadArtifacts node_type(?repo) in [ContainerRegistry, ArtifactRepository]

emit

source typeResourcePolicy
target typeFederatedIdentity
source?repo_policy
target<FederatedIdentity / WIF principalSet or principal>
permissionsartifactregistry.repositories.uploadArtifacts
conditionstrust_relationship condition_expression
state logicACTIVE when the trust condition on the WIF binding is BROAD or UNPINNED (the external identity assertion is easily satisfied — e.g. the principalSet covers all identities in the WIF pool, or the attribute mapping has no specific subject constraint). CONDITIONAL(trust_relationship) when the binding is pinned to a specific subject (e.g. a specific GitHub repo + branch ref), because the attacker must control an identity matching that subject. BLOCKED if the WIF pool is disabled or the pool's OIDC issuer is not trusted. Inherit weakest from the WIF pool's trust posture.

Narrative

Repository {repo.name} grants artifactregistry.repositories.uploadArtifacts to WIF identity {ext_identity.name}; an external OIDC workload (e.g. GitHub Actions runner) satisfying the attribute condition can push a malicious image directly to {repo.name} without any GCP service account key - supply-chain injection from external CI.

Raw rule rules/derived/gcp/artifactregistry.yaml

id: gcp-ar-wif-writer-trust
emits: TrustsExternalIdentity
description: "An Artifact Registry repo IAM binding for a Workload Identity Federation principalSet/principal\
  \ with uploadArtifacts grants an external OIDC identity (e.g. GitHub Actions) direct push access \u2014\
  \ supply-chain from external CI into GCP workloads."
match:
- - repo: null
  - HasPolicy
  - repo_policy: null
where:
- ?repo_policy is a ResourcePolicy of an Artifact Registry repository ?repo
- ?repo_policy has an IAM binding for a WIF principal (member starts with principalSet://iam.googleapis.com/
  or principal://iam.googleapis.com/)
- the binding role or permissions include artifactregistry.repositories.uploadArtifacts
- node_type(?repo) in [ContainerRegistry, ArtifactRepository]
emit:
  source_type: ResourcePolicy
  target_type: FederatedIdentity
  source: ?repo_policy
  target: <FederatedIdentity / WIF principalSet or principal>
  permissions:
  - artifactregistry.repositories.uploadArtifacts
  conditions:
  - trust_relationship
  - condition_expression
  state_logic: "ACTIVE when the trust condition on the WIF binding is BROAD or UNPINNED (the external\
    \ identity assertion is easily satisfied \u2014 e.g. the principalSet covers all identities in the\
    \ WIF pool, or the attribute mapping has no specific subject constraint). CONDITIONAL(trust_relationship)\
    \ when the binding is pinned to a specific subject (e.g. a specific GitHub repo + branch ref), because\
    \ the attacker must control an identity matching that subject. BLOCKED if the WIF pool is disabled\
    \ or the pool's OIDC issuer is not trusted. Inherit weakest from the WIF pool's trust posture."
  confidence: 0.85
  derived_from:
  - 'gcp-ar-wif-binding (explicit: TrustsExternalIdentity from IAM binding)'
  false_positive_note: "The strength of this edge depends entirely on the WIF attribute condition. A principalSet\
    \ that maps `google.subject` to `repo:org/repo:ref:refs/heads/main` is CONDITIONAL \u2014 the attacker\
    \ must push code to that specific branch. A principalSet covering all identities in the pool (no attribute\
    \ condition) is ACTIVE. Only emit this rule when grants_upload is true; read-only WIF bindings (downloadArtifacts\
    \ only) do not model supply-chain write risk and should not traverse this path for CanModifyCode derivations.\
    \ Cite federation-chains for the CanFederateAs -> CanEnterProject roll-up; do not re-derive it here.\
    \ The push permission itself is the Artifact Registry fact; the federation trust is the GCP WIF posture."
  narrative: "Repository {repo.name} grants artifactregistry.repositories.uploadArtifacts to WIF identity\
    \ {ext_identity.name}; an external OIDC workload (e.g. GitHub Actions runner) satisfying the attribute\
    \ condition can push a malicious image directly to {repo.name} without any GCP service account key\
    \ \u2014 supply-chain injection from external CI."
move · open · esc close