gcp-pubsub-update-subscription-can-modify-configuration
pubsub.subscriptions.update allows changing the push endpoint URL and push SA (oidcToken.serviceAccountEmail) on a subscription, enabling push-endpoint redirect for data exfiltration or push SA swap for credential exposure.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'match_effective_permission': {'action': 'pubsub.subscriptions.update', 'resource_type': 'google.pubsub.Subscription'}}
emit
| source type | Identity |
|---|---|
| target type | Queue |
| source | <principal> |
| target | <Pub/Sub subscription node> |
| permissions | pubsub.subscriptions.update |
| conditions | iam_permission |
| state logic | ACTIVE when effective pubsub.subscriptions.update is granted. Swapping the push SA field additionally requires iam.serviceAccounts.actAs on the new SA — if the principal lacks actAs on the desired SA, the push-SA-swap path is POTENTIAL (role_compatibility gate); the push-endpoint-redirect path remains ACTIVE. BLOCKED by IAM deny policy. |
Narrative
{principal.name} can update Pub/Sub subscription {subscription.name} (pubsub.subscriptions.update), redirecting its push endpoint to an attacker- controlled URL (data exfiltration of all messages) or swapping the push SA to deliver a different identity's OIDC token to the endpoint (requires actAs on the new SA).
Raw rule rules/derived/gcp/pubsub.yaml
id: gcp-pubsub-update-subscription-can-modify-configuration
emits: CanModifyConfiguration
description: pubsub.subscriptions.update allows changing the push endpoint URL and push SA (oidcToken.serviceAccountEmail)
on a subscription, enabling push-endpoint redirect for data exfiltration or push SA swap for credential
exposure.
match:
- match_effective_permission:
action: pubsub.subscriptions.update
resource_type: google.pubsub.Subscription
emit:
source_type: Identity
target_type: Queue
source: <principal>
target: <Pub/Sub subscription node>
permissions:
- pubsub.subscriptions.update
conditions:
- iam_permission
state_logic: "ACTIVE when effective pubsub.subscriptions.update is granted. Swapping the push SA field\
\ additionally requires iam.serviceAccounts.actAs on the new SA \u2014 if the principal lacks actAs\
\ on the desired SA, the push-SA-swap path is POTENTIAL (role_compatibility gate); the push-endpoint-redirect\
\ path remains ACTIVE. BLOCKED by IAM deny policy."
confidence: 0.9
derived_from:
- 'effective-permission: pubsub.subscriptions.update on subscription'
false_positive_note: "The push endpoint redirect (changing pushConfig.pushEndpoint) requires only pubsub.subscriptions.update\
\ \u2014 no actAs needed to change the URL. However, changing the oidcToken.serviceAccountEmail to\
\ an ARBITRARY SA requires iam.serviceAccounts.actAs on that SA; without it, GCP rejects the update.\
\ Do not conflate the two sub-capabilities: endpoint redirect is ACTIVE with only pubsub.subscriptions.update;\
\ SA swap is POTENTIAL without actAs. A pull subscription (no pushConfig) offers less interesting\
\ modification targets \u2014 changing deadLetterPolicy or filter is operationally impactful but does\
\ not directly yield an attack path; still emit CanModifyConfiguration for analyst awareness."
narrative: '{principal.name} can update Pub/Sub subscription {subscription.name} (pubsub.subscriptions.update),
redirecting its push endpoint to an attacker- controlled URL (data exfiltration of all messages) or
swapping the push SA to deliver a different identity''s OIDC token to the endpoint (requires actAs
on the new SA).'