Kubernetes Secret get or list from Node or Pod Service Account

Kubernetes audit identities for kubelet (system:node:*) and workloads (system:serviceaccount:*) are meant to operate with tight, predictable API usage. Direct get or list on the Secrets API from those principals is often a sign of credential access. Attackers who stole a pod service-account token or node credentials sweep Secret objects for tokens, registry credentials, TLS keys, or application configuration. Even denied attempts still reveal intent to reach sensitive material. Legitimate controllers do read secrets they mount or manage, so this signal is most valuable when paired with triage (namespace scope, user agent, RBAC, and whether the identity should touch those secret names at all).

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2026/04/22"
  3integration = ["kubernetes"]
  4maturity = "production"
  5updated_date = "2026/05/11"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Kubernetes audit identities for kubelet (`system:node:*`) and workloads (`system:serviceaccount:*`) are meant to
 11operate with tight, predictable API usage. Direct `get` or `list` on the Secrets API from those principals is
 12often a sign of credential access. Attackers who stole a pod service-account token or node credentials sweep Secret objects for
 13tokens, registry credentials, TLS keys, or application configuration. Even denied attempts still reveal intent to
 14reach sensitive material. Legitimate controllers do read secrets they mount or manage, so this signal is most valuable
 15when paired with triage (namespace scope, user agent, RBAC, and whether the identity should touch those secret names at
 16all).
 17"""
 18false_positives = [
 19    """
 20    In-cluster operators, CSI drivers, GitOps agents, and some platform controllers legitimately list or get Secrets in
 21    namespaces they manage; exclude known service accounts, namespaces, or user agents after baselining.
 22    """,
 23    """
 24    Rare kubelet or node maintenance tooling may touch Secret APIs; validate against change windows and approved node
 25    management paths.
 26    """,
 27]
 28index = ["logs-kubernetes.audit_logs-*"]
 29language = "kuery"
 30license = "Elastic License v2"
 31name = "Kubernetes Secret get or list from Node or Pod Service Account"
 32note = """## Triage and analysis
 33
 34### Investigating Kubernetes Secret get or list from Node or Pod Service Account
 35
 36This rule fires on Kubernetes audit events where the authenticated user is a node (`system:node:<nodename>`) or a
 37pod service account (`system:serviceaccount:<namespace>:<name>`) and the verb maps to read-style access
 38(`get`, `list`) on the **secrets** resource. Treat node-originated secret reads as high priority: kubelet should
 39not broadly enumerate cluster secrets. For service accounts, prioritize cross-namespace access, access to
 40high-value secret names, and clients that do not match the workload’s normal user agent or deployment.
 41
 42### Possible investigation steps
 43
 44- Resolve `user.name` (or `kubernetes.audit.user.username` if present) to the node or workload and review RBAC
 45  RoleBindings and ClusterRoleBindings for secret `get`/`list` scope.
 46- Inspect `kubernetes.audit.objectRef.namespace`, `kubernetes.audit.objectRef.name`, source IP, and
 47  `user_agent.original` for automation you recognize versus anomalous scripts or generic HTTP clients.
 48- Review `kubernetes.audit.annotations.authorization_k8s_io/decision` for successful reads versus probing denials.
 49- Correlate with pod exec, token creation, RoleBinding changes, or secret modification in the same time window.
 50
 51### False positive analysis
 52
 53- Controllers that reconcile Secrets (e.g. cert-manager, external-secrets, sealed-secrets) may match; allowlist their
 54  service accounts if behavior is expected and scoped.
 55- Helm and package managers can list release secrets during deploys; correlate with pipelines and chart releases.
 56
 57### Response and remediation
 58
 59- If malicious, revoke the token or node credentials, cordon or isolate the host or workload, rotate exposed secrets, and
 60  tighten RBAC to least privilege for the affected identity.
 61"""
 62references = [
 63    "https://attack.mitre.org/techniques/T1552/007/",
 64    "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens",
 65]
 66risk_score = 47
 67rule_id = "f8a31c62-0d4e-4b9a-b7e1-6c2a9d4e8f10"
 68severity = "medium"
 69tags = [
 70    "Data Source: Kubernetes",
 71    "Domain: Kubernetes",
 72    "Use Case: Threat Detection",
 73    "Tactic: Credential Access",
 74    "Resources: Investigation Guide",
 75]
 76timestamp_override = "event.ingested"
 77type = "query"
 78query = '''
 79data_stream.dataset:"kubernetes.audit_logs" and
 80event.action:(get or list) and
 81kubernetes.audit.objectRef.resource:"secrets" and
 82user.name:(system\:serviceaccount\:* or system\:node\:*) and source.ip:* and 
 83not kubernetes.audit.user.groups:(
 84  "system:serviceaccounts:flux-system"
 85  or "system:serviceaccounts:kyverno"
 86  or "system:serviceaccounts:ibm-csi"
 87  or "system:serviceaccounts:harvester-system"
 88  or "system:serviceaccounts:cattle-system"
 89  or "system:serviceaccounts:cattle-monitoring-system"
 90  or system\:serviceaccounts\:cluster-fleet-local-local-*
 91  or "system:serviceaccounts:rabbitmq-system"
 92  or "system:serviceaccounts:cattle-fleet-system"
 93)
 94'''
 95
 96[[rule.threat]]
 97framework = "MITRE ATT&CK"
 98
 99[[rule.threat.technique]]
100id = "T1552"
101name = "Unsecured Credentials"
102reference = "https://attack.mitre.org/techniques/T1552/"
103
104[[rule.threat.technique.subtechnique]]
105id = "T1552.007"
106name = "Container API"
107reference = "https://attack.mitre.org/techniques/T1552/007/"
108
109[rule.threat.tactic]
110id = "TA0006"
111name = "Credential Access"
112reference = "https://attack.mitre.org/tactics/TA0006/"

Triage and analysis

Investigating Kubernetes Secret get or list from Node or Pod Service Account

This rule fires on Kubernetes audit events where the authenticated user is a node (system:node:<nodename>) or a pod service account (system:serviceaccount:<namespace>:<name>) and the verb maps to read-style access (get, list) on the secrets resource. Treat node-originated secret reads as high priority: kubelet should not broadly enumerate cluster secrets. For service accounts, prioritize cross-namespace access, access to high-value secret names, and clients that do not match the workload’s normal user agent or deployment.

Possible investigation steps

  • Resolve user.name (or kubernetes.audit.user.username if present) to the node or workload and review RBAC RoleBindings and ClusterRoleBindings for secret get/list scope.
  • Inspect kubernetes.audit.objectRef.namespace, kubernetes.audit.objectRef.name, source IP, and user_agent.original for automation you recognize versus anomalous scripts or generic HTTP clients.
  • Review kubernetes.audit.annotations.authorization_k8s_io/decision for successful reads versus probing denials.
  • Correlate with pod exec, token creation, RoleBinding changes, or secret modification in the same time window.

False positive analysis

  • Controllers that reconcile Secrets (e.g. cert-manager, external-secrets, sealed-secrets) may match; allowlist their service accounts if behavior is expected and scoped.
  • Helm and package managers can list release secrets during deploys; correlate with pipelines and chart releases.

Response and remediation

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

References

Related rules

to-top