gcp-vertexai-create-workload-as-training
Create a Vertex AI custom training job / pipeline job / notebook execution job whose workers run as a passable SA (create + actAs). Job runs immediately on creation - no invoke step.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?principal has EFFECTIVE aiplatform.customJobs.create OR aiplatform.pipelineJobs.create OR aiplatform.notebookExecutionJobs.create in the target project/location
?principal has iam.serviceAccounts.actAs on ?sa (confirmed present)
emit
| source type | Identity |
|---|---|
| target type | ServiceAccount |
| source | <principal> |
| target | <service account> |
| permissions | aiplatform.customJobs.create iam.serviceAccounts.actAs |
| conditions | iam_permission role_compatibility |
| state logic | ACTIVE if iam.serviceAccounts.actAs on ?sa is confirmed AND the job-create permission is present (the job runs immediately — no trigger_exists gate; contrast with GCF). POTENTIAL(iam_permission) if actAs is not confirmed on ?sa. BLOCKED if org policy iam.disableCrossProjectServiceAccountUsage is active AND ?sa is in a different project. |
Narrative
{principal.name} can create a Vertex AI training job (aiplatform.customJobs.create) whose worker VMs run attacker-controlled code as {sa.name} (iam.serviceAccounts.actAs); the job runs on creation, no separate invocation needed.
Raw rule rules/derived/gcp/vertexai.yaml
id: gcp-vertexai-create-workload-as-training
emits: CanCreateWorkloadAs
description: "Create a Vertex AI custom training job / pipeline job / notebook execution job whose workers\
\ run as a passable SA (create + actAs). Job runs immediately on creation \u2014 no invoke step."
match:
- - principal: null
- CanPassIdentity
- sa: null
where:
- ?principal has EFFECTIVE aiplatform.customJobs.create OR aiplatform.pipelineJobs.create OR aiplatform.notebookExecutionJobs.create
in the target project/location
- ?principal has iam.serviceAccounts.actAs on ?sa (confirmed present)
emit:
source_type: Identity
target_type: ServiceAccount
source: <principal>
target: <service account>
permissions:
- aiplatform.customJobs.create
- iam.serviceAccounts.actAs
conditions:
- iam_permission
- role_compatibility
state_logic: "ACTIVE if iam.serviceAccounts.actAs on ?sa is confirmed AND the job-create permission\
\ is present (the job runs immediately \u2014 no trigger_exists gate; contrast with GCF). POTENTIAL(iam_permission)\
\ if actAs is not confirmed on ?sa. BLOCKED if org policy iam.disableCrossProjectServiceAccountUsage\
\ is active AND ?sa is in a different project."
derived_from:
- <CanPassIdentity edge_id>
false_positive_note: "No invoke/trigger gating \u2014 Vertex AI custom training creates and runs in\
\ a single API call. The attacker's container runs immediately with ?sa's credentials. actAs is required\
\ on the exact SA; without it -> POTENTIAL. If the SA is cross-project AND iam.disableCrossProjectServiceAccountUsage\
\ is active -> BLOCKED."
narrative: '{principal.name} can create a Vertex AI training job (aiplatform.customJobs.create) whose
worker VMs run attacker-controlled code as {sa.name} (iam.serviceAccounts.actAs); the job runs on
creation, no separate invocation needed.'