Detection rules › Elastic
GKE Service Account Token Created via TokenRequest API
Detects creation of a GKE service account token through the TokenRequest API by a non-system identity. TokenRequest allows programmatic minting of short-lived tokens for any service account the caller can create tokens for, without reading a mounted projected token from disk. Attackers with initial cluster access can abuse this API to obtain tokens for more privileged service accounts, pivot via Workload Identity to GCP APIs, or retain access after pod termination. Unlike filesystem token theft, TokenRequest activity is visible only in Kubernetes audit logs as create against the serviceaccounts/token subresource.
Known false positives
- Platform agents, admission webhooks, and CI jobs may legitimately call TokenRequest under non-standard identities. Baseline approved automation by client.user.email after validation. Expected GKE and kube-system controllers are excluded; expand exclusions if additional managed components appear in telemetry.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
Telemetry coverage
| Platform | Record / event type |
|---|---|
| Kubernetes | create-serviceaccounts-token: create serviceaccounts/token |
Rules detecting the same action
These rules filter on the same operation.
- Azure AKS Service Account Token Created via TokenRequest API (Elastic)
- Direct Interactive Kubernetes API Request by Unusual Utilities (Elastic)
- K8s Serviceaccount Created (Falco)
- Kubernetes Long-Lived Service Account Token Created (Panther)
- Kubernetes Service Account Token Created via TokenRequest API (Elastic)
- New Kubernetes Service Account Created (Sigma)
- Service Account Created in Kube Namespace (Falco)
Rule body
[metadata]
creation_date = "2026/07/13"
integration = ["gcp"]
maturity = "production"
updated_date = "2026/07/13"
[rule]
author = ["Elastic"]
description = """
Detects creation of a GKE service account token through the TokenRequest API by a non-system identity. TokenRequest
allows programmatic minting of short-lived tokens for any service account the caller can create tokens for, without
reading a mounted projected token from disk. Attackers with initial cluster access can abuse this API to obtain tokens
for more privileged service accounts, pivot via Workload Identity to GCP APIs, or retain access after pod termination.
Unlike filesystem token theft, TokenRequest activity is visible only in Kubernetes audit logs as create against the
serviceaccounts/token subresource.
"""
false_positives = [
"""
Platform agents, admission webhooks, and CI jobs may legitimately call TokenRequest under non-standard identities.
Baseline approved automation by client.user.email after validation. Expected GKE and kube-system controllers are
excluded; expand exclusions if additional managed components appear in telemetry.
""",
]
from = "now-6m"
index = ["logs-gcp.audit-*"]
language = "kuery"
license = "Elastic License v2"
name = "GKE Service Account Token Created via TokenRequest API"
note = """## Triage and analysis
### Investigating GKE Service Account Token Created via TokenRequest API
This alert indicates a successful create against the serviceaccounts/token subresource (TokenRequest API), which issues
a new service account token without a filesystem read. On GKE this can be abused to mint tokens for privileged service
accounts — including those bound through Workload Identity — and pivot to GCP APIs.
### Possible investigation steps
- Review `client.user.email`, `source.ip`, and `user_agent.original`.
- Identify the targeted service account from `gcp.audit.resource_name` (typically
`core/v1/namespaces/<ns>/serviceaccounts/<sa>/token`).
- Determine which Role or ClusterRoleBindings grant the actor `create` on `serviceaccounts/token`.
- Correlate the same actor and source with follow-on secret reads, pod exec, RBAC changes, or GCP API activity via
Workload Identity.
### False positive analysis
- New platform automation that mints projected tokens outside the excluded controllers may match. Allowlist after
confirming expected behavior.
### Response and remediation
- If unauthorized, remove or revert RBAC that allows TokenRequest and rotate the affected service account credentials.
- For Workload Identity-linked service accounts, revoke related GCP role sessions and review Cloud Audit Logs in the
same window.
"""
setup = """
The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule.
"""
references = [
"https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-v1/",
"https://stratus-red-team.cloud/attack-techniques/kubernetes/k8s.persistence.create-token/",
]
risk_score = 47
rule_id = "5d505bed-6d0e-4afa-b445-64841d4b8c58"
severity = "medium"
tags = [
"Domain: Cloud",
"Domain: Kubernetes",
"Data Source: GCP",
"Data Source: Google Cloud Platform",
"Use Case: Threat Detection",
"Tactic: Credential Access",
"Resources: Investigation Guide",
]
timestamp_override = "event.ingested"
type = "query"
query = '''
data_stream.dataset:gcp.audit and service.name:"k8s.io" and event.outcome:success and
event.action:"io.k8s.core.v1.serviceaccounts.token.create" and
client.user.email:(* and not (
"system:kube-controller-manager" or
"system:kube-scheduler" or
"system:gke-controller-manager" or
"system:gcp-controller-manager" or
system\:node\:* or
system\:serviceaccount\:kube-system\:* or
system\:serviceaccount\:gke-managed-system\:* or
system\:serviceaccount\:gke-connect\:* or
system\:serviceaccount\:anthos-identity-service\:*
))
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1552"
name = "Unsecured Credentials"
reference = "https://attack.mitre.org/techniques/T1552/"
[[rule.threat.technique.subtechnique]]
id = "T1552.007"
name = "Container API"
reference = "https://attack.mitre.org/techniques/T1552/007/"
[rule.threat.tactic]
id = "TA0006"
name = "Credential Access"
reference = "https://attack.mitre.org/tactics/TA0006/"
[rule.investigation_fields]
field_names = [
"@timestamp",
"client.user.email",
"source.ip",
"user_agent.original",
"event.action",
"event.outcome",
"gcp.audit.resource_name",
"gcp.audit.request",
"data_stream.namespace",
]
Stages and Predicates
Stage 1: query
data_stream.dataset:gcp.audit and service.name:"k8s.io" and event.outcome:success and
event.action:"io.k8s.core.v1.serviceaccounts.token.create" and
client.user.email:(* and not (
"system:kube-controller-manager" or
"system:kube-scheduler" or
"system:gke-controller-manager" or
"system:gcp-controller-manager" or
system\:node\:* or
system\:serviceaccount\:kube-system\:* or
system\:serviceaccount\:gke-managed-system\:* or
system\:serviceaccount\:gke-connect\:* or
system\:serviceaccount\:anthos-identity-service\:*
))
Exclusions
The rule actively suppresses these predicates.
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
client.user.email | is_not_null | field:"client.user.email" kind:is_not_null | |
data_stream.dataset | eq |
| field:"data_stream.dataset" kind:eq value:"gcp.audit" |
event.action | eq |
| field:"EventType" kind:eq value:"io.k8s.core.v1.serviceaccounts.token.create" |
event.outcome | eq |
| field:"event.outcome" kind:eq value:"success" |
service.name | eq |
| field:"ServiceName" kind:eq value:"k8s.io" |