gcp-sr-wif-writer-trust

A CSR repo IAM binding for a WIF principalSet/principal with source.repos.update grants an external OIDC identity (e.g. GitHub Actions) direct push access without any long-lived GCP key - supply-chain injection from external CI.

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 is a CSR ArtifactRepository ?repo_policy is a ResourcePolicy of the CSR repository ?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 source.repos.update

emit

source typeResourcePolicy
target typeFederatedIdentity
source?repo_policy
target<FederatedIdentity / WIF principalSet or principal>
permissionssource.repos.update
conditionstrust_relationship condition_expression
state logicACTIVE when the WIF binding attribute condition is BROAD or UNPINNED — the external assertion is easily satisfied (principalSet covers all pool identities, no specific subject constraint). CONDITIONAL(trust_relationship) when pinned to a specific external subject (e.g. a specific GitHub repo + branch ref), because the attacker must control a matching identity. BLOCKED if the WIF pool is disabled. Inherit weakest from the pool's trust posture. federation-chains::federation-maps-to-identity consumes this TrustsExternalIdentity + ExternalIdentityMapsTo to derive CanFederateAs -> CanEnterProject.

Narrative

Repository {repo.name} grants source.repos.update to WIF identity {ext_identity.name}; an external OIDC workload (e.g. GitHub Actions) satisfying the attribute condition can push commits directly to {repo.name} without any GCP service account key - supply-chain injection from external CI into any Cloud Build trigger watching a branch in {repo.name}. federation-chains rolls up the CanFederateAs and CanEnterProject consequences.

Raw rule rules/derived/gcp/sourcerepos.yaml

id: gcp-sr-wif-writer-trust
emits: TrustsExternalIdentity
description: "A CSR repo IAM binding for a WIF principalSet/principal with source.repos.update grants\
  \ an external OIDC identity (e.g. GitHub Actions) direct push access without any long-lived GCP key\
  \ \u2014 supply-chain injection from external CI."
match:
- - repo: null
  - HasPolicy
  - repo_policy: null
where:
- ?repo is a CSR ArtifactRepository
- ?repo_policy is a ResourcePolicy of the CSR repository
- ?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 source.repos.update
emit:
  source_type: ResourcePolicy
  target_type: FederatedIdentity
  source: ?repo_policy
  target: <FederatedIdentity / WIF principalSet or principal>
  permissions:
  - source.repos.update
  conditions:
  - trust_relationship
  - condition_expression
  state_logic: "ACTIVE when the WIF binding attribute condition is BROAD or UNPINNED \u2014 the external\
    \ assertion is easily satisfied (principalSet covers all pool identities, no specific subject constraint).\
    \ CONDITIONAL(trust_relationship) when pinned to a specific external subject (e.g. a specific GitHub\
    \ repo + branch ref), because the attacker must control a matching identity. BLOCKED if the WIF pool\
    \ is disabled. Inherit weakest from the pool's trust posture. federation-chains::federation-maps-to-identity\
    \ consumes this TrustsExternalIdentity + ExternalIdentityMapsTo to derive CanFederateAs -> CanEnterProject."
  confidence: 0.85
  derived_from:
  - 'IAM binding on ?repo_policy: WIF principalSet/principal has source.repos.update'
  - federation-chains::federation-maps-to-identity (for CanFederateAs consequence)
  false_positive_note: "The strength depends entirely on the WIF attribute condition. A principalSet mapping\
    \ google.subject == 'repo:org/repo:ref:refs/heads/main' is CONDITIONAL \u2014 the attacker must push\
    \ code to that branch in that repo. A principalSet covering all pool identities (no attribute condition)\
    \ is ACTIVE. Cite federation-chains for the CanFederateAs -> CanEnterProject roll-up; do not re-derive\
    \ it here."
  narrative: "Repository {repo.name} grants source.repos.update to WIF identity {ext_identity.name}; an\
    \ external OIDC workload (e.g. GitHub Actions) satisfying the attribute condition can push commits\
    \ directly to {repo.name} without any GCP service account key \u2014 supply-chain injection from external\
    \ CI into any Cloud Build trigger watching a branch in {repo.name}. federation-chains rolls up the\
    \ CanFederateAs and CanEnterProject consequences."
move · open · esc close