gcp-cloudscheduler-run-job
cloudscheduler.jobs.run triggers an immediate execution of the current job definition, bypassing the cron schedule - the on-demand CanSchedule primitive for an existing Cloud Scheduler job.
match (effective permission)
{
"action": "cloudscheduler.jobs.run",
"resource_type": "google.cloud.scheduler.v1.Job"
}
emit
| source type | Identity |
|---|---|
| target type | Scheduler |
| source | <principal> |
| target | <Cloud Scheduler job (Scheduler node)> |
| permissions | cloudscheduler.jobs.run |
| conditions | iam_permission service_state |
| state logic | ACTIVE when the principal holds cloudscheduler.jobs.run AND the job state is ENABLED (or PAUSED — paused jobs can still be manually triggered via the run method). BLOCKED when the job state is DISABLED or UPDATE_FAILED. BLOCKED by IAM deny on jobs.run. |
Narrative
{principal.name} can immediately trigger {job.name} (cloudscheduler.jobs.run), bypassing the cron schedule and forcing the job to fire against its current target with its configured OIDC/OAuth2 SA credentials.
Raw rule rules/derived/gcp/cloudscheduler.yaml
id: gcp-cloudscheduler-run-job
emits: CanSchedule
description: "cloudscheduler.jobs.run triggers an immediate execution of the current job definition, bypassing\
\ the cron schedule \u2014 the on-demand CanSchedule primitive for an existing Cloud Scheduler job."
match_effective_permission:
action: cloudscheduler.jobs.run
resource_type: google.cloud.scheduler.v1.Job
emit:
source_type: Identity
target_type: Scheduler
source: <principal>
target: <Cloud Scheduler job (Scheduler node)>
permissions:
- cloudscheduler.jobs.run
derived_from:
- 'effective permission: cloudscheduler.jobs.run on the job resource'
conditions:
- iam_permission
- service_state
state_logic: "ACTIVE when the principal holds cloudscheduler.jobs.run AND the job state is ENABLED (or\
\ PAUSED \u2014 paused jobs can still be manually triggered via the run method). BLOCKED when the\
\ job state is DISABLED or UPDATE_FAILED. BLOCKED by IAM deny on jobs.run."
false_positive_note: 'jobs.run triggers the CURRENT job definition immediately. If the attacker previously
updated the job (cloudscheduler.jobs.update) to retarget or swap the SA, jobs.run activates that modified
configuration without waiting for the next scheduled time. This CanSchedule (immediate run) feeds
the same messaging-chains roll-ups as the create-based CanSchedule: combined with an existing CanTrigger(job
-> compute) and ExecutesAs(compute -> SA) it yields CanExecuteAs via messaging-chains rules 1+2. PAUSED
state: the API docs confirm paused jobs can be run manually via the run method (the pause only stops
scheduled firing, not on-demand runs).'
narrative: '{principal.name} can immediately trigger {job.name} (cloudscheduler.jobs.run), bypassing
the cron schedule and forcing the job to fire against its current target with its configured OIDC/OAuth2
SA credentials.'