gcp-tasks-queue-dispatches-to-consumer

A Cloud Tasks queue with httpTarget.uri (or an App Engine target) dispatches tasks to its configured consumer HTTP endpoint - the event-source binding fact consumed by messaging-chains rule 1.

derived gcp emits CanTrigger

match (record)

{ "field": "httpTarget.uri", "resource_type": "google.cloud.tasks.v2.Queue" }

where

queue.httpTarget.uri is set AND resolves to an HTTP/HTTPS endpoint modeled as a Compute consumer (Cloud Run service, Cloud Function, App Engine handler, or GenericCompute endpoint) queue.state == RUNNING OR PAUSED (binding is real even if paused)

emit

source typeQueue
target typeCompute
source<Cloud Tasks queue>
target<consumer compute node at httpTarget.uri>
conditionsservice_state trigger_exists
state logicACTIVE when queue.state == RUNNING and the consumer endpoint is reachable and registered (Cloud Run service enabled, GCF deployed). CONDITIONAL(service_state) when queue.state == PAUSED — binding is real but dispatch is suspended. CONDITIONAL(trigger_exists) when the consumer endpoint URL resolves to a node that is not currently deployed/enabled. Do not emit for DISABLED queues.

Narrative

Queue {queue.name} is configured to dispatch HTTP tasks to {consumer.name} (httpTarget.uri = {uri}). A published task reaches {consumer.name} with an attacker-influenced body, forming the event-source binding that messaging-chains rolls into CanTrigger(principal → consumer) when combined with CanWriteData.

Raw rule rules/derived/gcp/tasks.yaml

id: gcp-tasks-queue-dispatches-to-consumer
emits: CanTrigger
description: "A Cloud Tasks queue with httpTarget.uri (or an App Engine target) dispatches tasks to its\
  \ configured consumer HTTP endpoint \u2014 the event-source binding fact consumed by messaging-chains\
  \ rule 1."
match_record:
  resource_type: google.cloud.tasks.v2.Queue
  field: httpTarget.uri
where:
- queue.httpTarget.uri is set AND resolves to an HTTP/HTTPS endpoint modeled as a Compute consumer (Cloud
  Run service, Cloud Function, App Engine handler, or GenericCompute endpoint)
- queue.state == RUNNING OR PAUSED (binding is real even if paused)
emit:
  source_type: Queue
  target_type: Compute
  source: <Cloud Tasks queue>
  target: <consumer compute node at httpTarget.uri>
  permissions: []
  conditions:
  - service_state
  - trigger_exists
  state_logic: "ACTIVE when queue.state == RUNNING and the consumer endpoint is reachable and registered\
    \ (Cloud Run service enabled, GCF deployed). CONDITIONAL(service_state) when queue.state == PAUSED\
    \ \u2014 binding is real but dispatch is suspended. CONDITIONAL(trigger_exists) when the consumer\
    \ endpoint URL resolves to a node that is not currently deployed/enabled. Do not emit for DISABLED\
    \ queues."
  derived_from:
  - queue.httpTarget.uri field from cloudtasks.queues.get
  false_positive_note: "Only emit when httpTarget.uri actually resolves to a modeled Compute node (Cloud\
    \ Run service URL, GCF HTTPS trigger URL, App Engine default service URL). An external/non-GCP endpoint\
    \ is still a CanTrigger target \u2014 model as GenericCompute and note that ExecutesAs is unknown\
    \ for non-GCP consumers. Do NOT emit for queues with appEngineHttpQueue target using a fully blank\
    \ routing (the handler is the App Engine default service, which is still a valid consumer \u2014 emit\
    \ with target_type ApplicationPlatform). A queue with no httpTarget.uri and no appEngineHttpQueue\
    \ is not yet bound to a consumer; do not emit."
  narrative: "Queue {queue.name} is configured to dispatch HTTP tasks to {consumer.name} (httpTarget.uri\
    \ = {uri}). A published task reaches {consumer.name} with an attacker-influenced body, forming the\
    \ event-source binding that messaging-chains rolls into CanTrigger(principal \u2192 consumer) when\
    \ combined with CanWriteData."
move · open · esc close