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.
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 |
| 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. |
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.'