gcp-cloudscheduler-job-body-contains-secret

A Cloud Scheduler job's HTTP body (httpTarget.body) or Pub/Sub payload (pubsubTarget.data) may embed credentials. Any principal with cloudscheduler.jobs.get / fullView can read the job definition and recover the embedded credential.

derived gcp emits ContainsSecret

match (record)

{ "field": "httpTarget.body | pubsubTarget.data", "resource_type": "google.cloud.scheduler.v1.Job" }

where

base64-decoded body matches a credential pattern (API key, SA key JSON, password, OAuth2 token, connection string)

emit

source typeMessaging
target typeSecret
source<Cloud Scheduler job (Scheduler node)>
target<secret / credential material in the job body>
conditionsiam_permission
state logicACTIVE when the job body/data field is classified as containing a credential pattern (confirmed by pattern matching on base64-decoded payload). CONDITIONAL(iam_permission) when the principal's ability to read cloudscheduler.jobs.fullView is unconfirmed. BLOCKED when no credential pattern is detected in the payload. The embedded secret drives downstream ExposesCredential and CredentialsFor edges via credential-chains.

Narrative

{job.name}'s request payload contains credential material (embedded in httpTarget.body or pubsubTarget.data), recoverable by any principal with cloudscheduler.jobs.get.

Raw rule rules/derived/gcp/cloudscheduler.yaml

id: gcp-cloudscheduler-job-body-contains-secret
emits: ContainsSecret
description: A Cloud Scheduler job's HTTP body (httpTarget.body) or Pub/Sub payload (pubsubTarget.data)
  may embed credentials. Any principal with cloudscheduler.jobs.get / fullView can read the job definition
  and recover the embedded credential.
match_record:
  resource_type: google.cloud.scheduler.v1.Job
  field: httpTarget.body | pubsubTarget.data
where:
- base64-decoded body matches a credential pattern (API key, SA key JSON, password, OAuth2 token, connection
  string)
emit:
  source_type: Messaging
  target_type: Secret
  source: <Cloud Scheduler job (Scheduler node)>
  target: <secret / credential material in the job body>
  permissions: []
  derived_from:
  - job.httpTarget.body or job.pubsubTarget.data field classification
  conditions:
  - iam_permission
  state_logic: ACTIVE when the job body/data field is classified as containing a credential pattern (confirmed
    by pattern matching on base64-decoded payload). CONDITIONAL(iam_permission) when the principal's ability
    to read cloudscheduler.jobs.fullView is unconfirmed. BLOCKED when no credential pattern is detected
    in the payload. The embedded secret drives downstream ExposesCredential and CredentialsFor edges via
    credential-chains.
  false_positive_note: "Only emit when classification of the body/data field yields a confirmed credential\
    \ pattern \u2014 not for every job. Many job bodies contain operational payloads (JSON data, task\
    \ identifiers) with no credential material. False-positive rate is high without classifier confirmation.\
    \ cloudscheduler.jobs.fullView permission is needed to read the full body in the API response (it\
    \ is included in roles/cloudscheduler.viewer, roles/cloudscheduler.admin, roles/cloudscheduler.jobRunner)."
  narrative: '{job.name}''s request payload contains credential material (embedded in httpTarget.body
    or pubsubTarget.data), recoverable by any principal with cloudscheduler.jobs.get.'
move · open · esc close