GKE Secret Access from Node or Denied Service Account

Detects GKE Secrets API activity that should not occur in normal cluster operation: a node identity (system:node:*) performing secrets get or list, or a pod service account failing a secrets get. Kubelet and node credentials are not expected to call the Secrets API for enumeration or direct reads, and a denied service-account secret get could indicate stolen-token probing or over-privileged tooling reaching beyond its RBAC.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/07/17"
  3integration = ["gcp"]
  4maturity = "production"
  5updated_date = "2026/07/17"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects GKE Secrets API activity that should not occur in normal cluster operation: a node identity
 11(system:node:*) performing secrets get or list, or a pod service account failing a secrets get.
 12Kubelet and node credentials are not expected to call the Secrets API for enumeration or direct reads,
 13and a denied service-account secret get could indicate stolen-token probing or over-privileged tooling
 14reaching beyond its RBAC.
 15"""
 16false_positives = [
 17    """
 18    Rare node maintenance or diagnostic tooling may touch the Secrets API; validate against change windows
 19    and approved node management paths.
 20    """,
 21    """
 22    Misconfigured workloads can generate repeated denied secret gets during startup; confirm RBAC intent
 23    before treating as compromise.
 24    """,
 25]
 26from = "now-6m"
 27index = ["logs-gcp.audit-*"]
 28language = "kuery"
 29license = "Elastic License v2"
 30name = "GKE Secret Access from Node or Denied Service Account"
 31note = """## Triage and analysis
 32
 33### Investigating GKE Secret Access from Node or Denied Service Account
 34
 35This rule fires on two high-confidence patterns in GKE audit logs:
 36
 37- `system:node:*` successfully or unsuccessfully calling `secrets.get` or `secrets.list`
 38- `system:serviceaccount:*` receiving `event.outcome:failure` on `secrets.get`
 39
 40Treat node-originated Secrets API calls as priority. For denied service-account gets, determine whether
 41the identity is probing secrets outside its Role/ClusterRole or using an unexpected client from a
 42compromised token.
 43
 44### Possible investigation steps
 45
 46- Resolve `client.user.email` to the node or workload and review RBAC bindings for secret `get`/`list` scope.
 47- Inspect `gcp.audit.resource_name`, `source.ip`, and `user_agent.original` for anomalous clients or
 48  cross-namespace targets.
 49- Correlate with successful secret reads, pod exec, token creation, or RoleBinding changes in the same window.
 50- For node events, confirm whether kubelet, CSI, or maintenance tooling on that node should ever call the
 51  Secrets API.
 52
 53### False positive analysis
 54
 55- Node diagnostics or custom CSI helpers may rarely issue Secrets API calls; allowlist only after confirming
 56  the path is approved.
 57- Broken RBAC on a newly deployed workload can produce repeated denied gets until permissions are fixed.
 58
 59### Response and remediation
 60
 61- If malicious, revoke the node or service-account credentials, isolate the host or workload, rotate exposed
 62  secrets, and tighten RBAC to least privilege for the affected identity.
 63"""
 64setup = "The GCP Fleet integration with GKE audit logs enabled is required to be compatible with this rule."
 65references = [
 66    "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens",
 67]
 68risk_score = 47
 69rule_id = "bedab6b4-f195-45d1-8f97-7d300eb79671"
 70severity = "medium"
 71tags = [
 72    "Domain: Cloud",
 73    "Domain: Kubernetes",
 74    "Data Source: GCP",
 75    "Data Source: Google Cloud Platform",
 76    "Use Case: Threat Detection",
 77    "Tactic: Credential Access",
 78    "Resources: Investigation Guide",
 79]
 80timestamp_override = "event.ingested"
 81type = "query"
 82
 83query = '''
 84data_stream.dataset:gcp.audit and service.name:k8s.io and
 85source.ip:(* and not (127.0.0.1 or "::1")) and
 86(
 87  (
 88    client.user.email:system\:node\:* and
 89    event.action:(io.k8s.core.v1.secrets.get or io.k8s.core.v1.secrets.list)
 90  ) or (
 91    client.user.email:system\:serviceaccount\:* and
 92    event.action:io.k8s.core.v1.secrets.get and
 93    event.outcome:failure
 94  )
 95)
 96'''
 97
 98[[rule.threat]]
 99framework = "MITRE ATT&CK"
100
101[[rule.threat.technique]]
102id = "T1552"
103name = "Unsecured Credentials"
104reference = "https://attack.mitre.org/techniques/T1552/"
105
106[[rule.threat.technique.subtechnique]]
107id = "T1552.007"
108name = "Container API"
109reference = "https://attack.mitre.org/techniques/T1552/007/"
110
111[rule.threat.tactic]
112id = "TA0006"
113name = "Credential Access"
114reference = "https://attack.mitre.org/tactics/TA0006/"
115
116[rule.investigation_fields]
117field_names = [
118    "@timestamp",
119    "client.user.email",
120    "source.ip",
121    "user_agent.original",
122    "event.action",
123    "event.outcome",
124    "gcp.audit.resource_name",
125    "data_stream.namespace",
126]

Triage and analysis

Investigating GKE Secret Access from Node or Denied Service Account

This rule fires on two high-confidence patterns in GKE audit logs:

  • system:node:* successfully or unsuccessfully calling secrets.get or secrets.list
  • system:serviceaccount:* receiving event.outcome:failure on secrets.get

Treat node-originated Secrets API calls as priority. For denied service-account gets, determine whether the identity is probing secrets outside its Role/ClusterRole or using an unexpected client from a compromised token.

Possible investigation steps

  • Resolve client.user.email to the node or workload and review RBAC bindings for secret get/list scope.
  • Inspect gcp.audit.resource_name, source.ip, and user_agent.original for anomalous clients or cross-namespace targets.
  • Correlate with successful secret reads, pod exec, token creation, or RoleBinding changes in the same window.
  • For node events, confirm whether kubelet, CSI, or maintenance tooling on that node should ever call the Secrets API.

False positive analysis

  • Node diagnostics or custom CSI helpers may rarely issue Secrets API calls; allowlist only after confirming the path is approved.
  • Broken RBAC on a newly deployed workload can produce repeated denied gets until permissions are fixed.

Response and remediation

  • If malicious, revoke the node or service-account credentials, isolate the host or workload, rotate exposed secrets, and tighten RBAC to least privilege for the affected identity.

References

Related rules

to-top