gcp-ar-repo-update-config

artifactregistry.repositories.update can disable tag immutability, change remote/virtual repo upstreams, or otherwise reconfigure a repository - enabling subsequent supply-chain attacks that were previously BLOCKED.

derived gcp emits CanModifyConfiguration

match (effective permission)

{ "action": "artifactregistry.repositories.update", "resource_type": "google.artifactregistry.Repository" }

emit

source typeIdentity
target type*
source<principal>
target<Artifact Registry repository in scope>
permissionsartifactregistry.repositories.update
state logicACTIVE when the permission is effective. The downstream consequence depends on the repo type: for a ContainerRegistry (Docker/OCI) with ImmutableTags: true, this configuration change UNLOCKS the tag-overwrite path (transitioning the subsequent CanModifyCode to ACTIVE from BLOCKED/CONDITIONAL). For a remote repo, changing the upstream URL redirects pull traffic to an attacker-controlled origin. BLOCKED if an IAM deny policy denies artifactregistry.repositories.update. Inherits weakest from contributing role binding.

Narrative

{principal.name} can update the configuration of repository {repo.name} (artifactregistry.repositories.update), for example disabling tag immutability to enable tag overwrite, or changing a remote repo's upstream URL to redirect pulls to an attacker-controlled source.

Raw rule rules/derived/gcp/artifactregistry.yaml

id: gcp-ar-repo-update-config
emits: CanModifyConfiguration
description: "artifactregistry.repositories.update can disable tag immutability, change remote/virtual\
  \ repo upstreams, or otherwise reconfigure a repository \u2014 enabling subsequent supply-chain attacks\
  \ that were previously BLOCKED."
match_effective_permission:
  action: artifactregistry.repositories.update
  resource_type: google.artifactregistry.Repository
emit:
  source_type: Identity
  target_type: '*'
  source: <principal>
  target: <Artifact Registry repository in scope>
  permissions:
  - artifactregistry.repositories.update
  conditions: []
  state_logic: 'ACTIVE when the permission is effective. The downstream consequence depends on the repo
    type: for a ContainerRegistry (Docker/OCI) with ImmutableTags: true, this configuration change UNLOCKS
    the tag-overwrite path (transitioning the subsequent CanModifyCode to ACTIVE from BLOCKED/CONDITIONAL).
    For a remote repo, changing the upstream URL redirects pull traffic to an attacker-controlled origin.
    BLOCKED if an IAM deny policy denies artifactregistry.repositories.update. Inherits weakest from contributing
    role binding.'
  confidence: 0.85
  derived_from:
  - 'effective permission: artifactregistry.repositories.update on <repo>'
  false_positive_note: 'CanModifyConfiguration on a repo does NOT itself push code; it is a precondition
    that unlocks a subsequent push (immutability removal) or redirects pulls (upstream change). The escalation
    consequence is CONDITIONAL on both the config change AND a subsequent push or pull from the changed
    upstream. For the immutability-removal path, emit CanModifyCode for the subsequent push as CONDITIONAL
    (precondition: immutability was removed) rather than ACTIVE, unless the principal also holds uploadArtifacts.
    For the remote-upstream-change path, the dependency confusion vector does not require any further
    GCP permission; the attacker must control a public upstream package at the right version. The target_type
    is resolved at emit time from the repository''s generic_type (ContainerRegistry for Docker/OCI, ArtifactRepository
    for package repos).'
  narrative: '{principal.name} can update the configuration of repository {repo.name} (artifactregistry.repositories.update),
    for example disabling tag immutability to enable tag overwrite, or changing a remote repo''s upstream
    URL to redirect pulls to an attacker-controlled source.'
move · open · esc close