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.
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 type | Messaging |
|---|---|
| target type | Secret |
| source | <Cloud Scheduler job (Scheduler node)> |
| target | <secret / credential material in the job body> |
| 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. |
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.'