<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Isai Anthony - Elastic Security Labs]]></title>
    <description><![CDATA[Trusted security news & research from the team at Elastic.]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Isai Anthony - Elastic Security Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte2c6b841aff36df4/6a88d9784acc96e3f324863d/security-labs-thumbnail.png</url>
      <link>https://www.elastic.co/security-labs/author/isai-anthony</link>
    </image>
    <link>https://www.elastic.co/security-labs/author/isai-anthony</link>
    <atom:link href="https://www.elastic.co/security-labs/rss/author/isai-anthony.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[en]]></language>
    <lastBuildDate>Sun, 13 Sep 2026 11:04:02 GMT</lastBuildDate>
  <item>
    <title><![CDATA[How to correlate Kubernetes audit logs with container runtime data]]></title>
    <description><![CDATA[Two fields join the Kubernetes API to what ran inside the pod, and one turns up a container escape your process events never recorded.]]></description>
    <content:encoded><![CDATA[<p>If you already ship Kubernetes (K8s) audit logs and Defend for Containers (D4C) into Elastic, you still have to join them by hand, and neither source is complete on its own. In our lab, a compromised workload service account ran discovery, read secrets, minted a token, created a privileged pod, and execed into it to attempt a container escape. The escape wrappers, <code>nsenter</code> and <code>chroot</code>, never appeared in the runtime process events. Kubernetes audit logs recorded them in the decoded <code>requestURI</code>.</p><p>Real incidents cross both planes, which is why our write-up of the <a href="https://www.elastic.co/security-labs/threat-command/ai-agent-attack-detection-hugging-face-breach">Hugging Face intrusion</a> shows Kubernetes and runtime abuse in the same campaign. The two data sources answer different questions:</p><p></p><p>Data source</p><p>Typical data streams</p><p>What it answers</p><p>Kubernetes audit</p><p><code>logs-kubernetes.audit_logs-*</code></p><p>Who called the API and which objects changed</p><p>D4C</p><p><code>logs-cloud_defend.process*</code>, <code>logs-cloud_defend.file*</code>, <code>logs-cloud_defend.alerts*</code></p><p>What ran or changed inside the container</p><p>This post makes that connection practical in Elastic. We cover the fields that join the two data sources and two ways to join across them, depending on how the API call is attributed. We also cover the one-sided context fields that help you read the activity. Plus, we walk through each of those with queries and result views from our Amazon Elastic Kubernetes Service (EKS) lab.</p><p>This continues the control-plane correlation thread from the <a href="https://www.elastic.co/security-labs/teampcp-container-attack-scenario">TeamPCP container attack scenario</a>. For D4C setup and policy basics, see <a href="https://www.elastic.co/security-labs/getting-started-with-defend-for-containers">Getting started with Defend for Containers</a>.</p><h2>How Kubernetes audit logs and container runtime data connect</h2><p>Two joins cover most cases. Which one you use depends on how Kubernetes attributed the API call.</p><p>
</p><p>Pod caller identity</p><p>Service account and objectRef</p><p>When to use it</p><p>The audit event carries the pod-name extra, which happens when a request uses the pod's bound service account identity from inside the pod</p><p>The call is attributed only as a service account in <code>user.name</code>, with no pod-name extra on the event</p><p>Kubernetes audit field</p><p><code>kubernetes.audit.user.extra.</code>
<code>authentication.kubernetes.io/pod-name</code></p><p><code>kubernetes.audit.objectRef.name</code>, filtered to <code>objectRef.resource: pods</code></p><p>Container runtime field</p><p><code>orchestrator.resource.name</code></p><p><code>orchestrator.resource.name</code>, plus <code>orchestrator.namespace</code></p><p>What you get</p><p>Direct attribution; the pod that made the API call is the pod you look at in runtime</p><p>The pods a suspicious service account created or execed into, as a set to investigate</p><p>Limits</p><p>Only works when the pod-name extra is present, so it misses calls attributed as a bare service account</p><p>If more than one service account touched the same pod in your window, runtime gives shared context rather than clean attribution</p><h3>Join keys shared by Kubernetes audit logs and container runtime</h3><p>These fields carry the same meaning on both data sources. Pair them with a time window around the activity you care about (often 15 to 60 minutes).</p><p>Join idea</p><p>D4C field</p><p>Kubernetes audit field</p><p>How it connects</p><p>Namespace</p><p><code>orchestrator.</code>
<code>namespace</code></p><p><code>orchestrator.namespace</code>
 or <code>kubernetes.audit</code>
<code>.objectRef.namespace</code></p><p>Scopes both data sources to the same workload space</p><p>Cluster</p><p><code>orchestrator.</code>
<code>cluster.name</code></p><p><code>orchestrator.cluster.name</code></p><p>Keeps multi-cluster environments from mixing</p><p>Time</p><p><code>@timestamp</code></p><p><code>@timestamp</code></p><p>Bounds the join</p><p>Pod (create → use)</p><p><code>orchestrator.</code>
<code>resource.name</code></p><p><code>kubernetes.audit.objectRef.name</code> when the audit event is about that pod (create, exec, and similar)</p><p>Links a control-plane change to runtime inside the new or targeted pod</p><p>Pod (caller identity)</p><p><code>orchestrator.</code>
<code>resource.name</code></p><p><code>kubernetes.audit.</code>
<code>user.extra.authentication</code>
<code>.kubernetes.io/pod-name</code></p><p>Links runtime in a pod to API calls Kubernetes attributes to that same calling pod</p><p>One of the most useful pod joins for tracking threat behavior is create and then use. K8s audit records the create (or an exec) and names the pod. We then use that same pod name on the D4C side to see what ran inside it a few minutes later. Once you know the namespace and pod name, look for matching <code>orchestrator.namespace</code> and <code>orchestrator.resource.name</code>, and then scan <code>process.name</code> and <code>process.args</code> for what ran in that pod.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2655c23530845d5e/6a9699b06fe145a329b1c821/image1.png" alt="Kubernetes audit logs pod create joined to container runtime process events on orchestrator.resource.name in ES|QL" /><h3>Joining on pod caller identity</h3><p>Some Elastic prebuilt rules correlate D4C and K8s audit in one detection using <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/eql">Event Query Language</a> (EQL) sequences across both data sources. <a href="https://github.com/elastic/detection-rules/blob/43a60b86c1ad3c9d618d571581556f306d2c4b00/rules/cross-platform/execution_d4c_k8s_mda_service_account_token_access_followed_by_kubernetes_api_request.toml">Service Account Token or Certificate Access Followed by Kubernetes API Request</a> is a useful example of the pod (caller identity) join from the table above. Within 60 seconds, it joins a service account token or digital certificate file open on <code>orchestrator.resource.name</code> to a Kubernetes audit API event on <code>kubernetes.audit.user.extra.authentication.kubernetes.io/pod-name</code>.</p>sequence with maxspan=60s
 [file where host.os.type == "linux" and event.type == "change" and event.action == "open" and
  file.path in (
    "/var/run/secrets/kubernetes.io/serviceaccount/token",
    "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
  ) and
  process.interactive == true and container.id like "*"] by orchestrator.resource.name
 [any where data_stream.dataset == "kubernetes.audit_logs" and
  kubernetes.audit.stage in ("ResponseComplete", "ResponseStarted")]
  by `kubernetes.audit.user.extra.authentication.kubernetes.io/pod-name`<p>That pod-name extra on a Kubernetes audit event is often present when a request uses the pod’s bound service account (SA) identity, including controllers and agents that call the API from inside the pod. When it’s present, you can line it up with the D4C field <code>orchestrator.resource.name</code>, including in sequence rules like the one above. Some API traffic is attributed only as a service account in <code>user.name</code>, without the pod-name extra. That requires a different join; start from the SA, collect pod names from <code>objectRef</code>, and carry those into D4C with the namespace and a shared time window. That path is shown next. </p><h3>Joining on service account and objectRef pod names</h3><p>Caller identity joins on the pod that made the API call. This section joins on the service account principal and the pods it touched. Both are valid ways to move between Kubernetes audit and D4C; which one fits depends on how the audit event is attributed.</p><p>This join assumes a compromised or suspicious service account is driving API activity and that the pods it creates or execs into are where we should look next in D4C.</p><p>The join runs in three steps:</p><ol><li><p><strong>Timeline the service account in Kubernetes audit logs.</strong> Filter on <code>user.name</code> matching <code>system:serviceaccount:&lt;namespace&gt;:&lt;sa&gt;</code> to see every API call that principal made and which objects it touched.</p></li><li><p><strong>Collect pod names from </strong><strong><code>kubernetes.audit.objectRef.name</code></strong><strong>.</strong> Keep the rows where <code>objectRef.resource</code> is <code>pods</code>, which covers both creates and execs, and note the namespace from <code>orchestrator.namespace</code>.</p></li><li><p><strong>Query Defend for Containers with those pod names and namespace.</strong> Match <code>orchestrator.resource.name</code> against the pod names and <code>orchestrator.namespace</code> against the namespace, using the same time window as the audit activity.</p></li></ol><p>Each step is expanded below with the queries we ran.</p><p>Kubernetes audit carries the API principal in <code>user.name</code> (and <code>kubernetes.audit.user.username</code>), for example <code>system:serviceaccount:&lt;namespace&gt;:&lt;sa&gt;</code>. On a D4C process event, that K8s principal isn’t present as <code>user.name</code>, and <code>user.id</code> is the Linux user ID inside the container (for example, <code>0</code> when the process runs as root). There are different mappings from different integrations, so even when both documents expose a field by the same name, the value reflects that data source’s schema, which isn’t always a 1:1 correlation.</p><p>A good approach is to timeline the suspicious service account in audit. This shows what that principal did and which objects it touched:</p><strong>user.name: "system:serviceaccount:&lt;namespace&gt;:&lt;sa&gt;"</strong><p>Or as Elasticsearch Query Language (ES|QL), keeping the fields that matter for the next hop:</p><p>In the service account timeline results, look at <code>kubernetes.audit.verb</code>, <code>objectRef.resource</code>, <code>objectRef.subresource</code>, <code>orchestrator.namespace</code>, and <code>objectRef.name</code> for what was touched.</p><p>Collect pod names from the objects that SA touched. For pod creates and execs, the pod sits in <code>kubernetes.audit.objectRef.name</code>, the namespace in <code>orchestrator.namespace</code>, and the verb in <code>kubernetes.audit.verb</code>, and exec shows up as <code>kubernetes.audit.objectRef.subresource: exec (with objectRef.resource: pods</code><code>)</code>. Filter the same SA timeline to create and exec activity when you only want pod targets:</p>data_stream.dataset: "kubernetes.audit_logs" and 
user.name: "system:serviceaccount:&lt;namespace&gt;:&lt;sa&gt;" and
kubernetes.audit.objectRef.resource: pods and
(
  kubernetes.audit.verb: create or
  kubernetes.audit.objectRef.subresource: exec
)<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt41c1fae7143d9f58/6a969af8d05d4c7244581d71/image2.png" alt="Kubernetes audit logs filtered to pod create and exec rows showing objectRef.name and orchestrator.namespace" /><p>Query D4C with those pod names and the shared namespace. Use the namespace and pod names you collected (and the same time window as the audit activity):</p>data_stream.dataset: "cloud_defend.*" and 
orchestrator.namespace: "&lt;namespace&gt;" and 
orchestrator.resource.name: ("&lt;pod-1&gt;" or "&lt;pod-2&gt;")<p>If more than one service account creates or execs into the same pod in that window, D4C on that pod name shows shared runtime context, not a clean attribution back to a single SA.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt70cc06de87768e87/6a969b2c8057557cbb7044d4/image10.png" alt="Defend for Containers results for the namespace and pod names collected from the Kubernetes audit logs timeline" /><p>Namespace and pod name work in the other direction too. Starting from a Defend for Containers process event, take <code>orchestrator.namespace</code> and <code>orchestrator.resource.name</code> and search Kubernetes audit logs for that pod in <code>objectRef</code> to recover create, exec, and related API activity.</p><h2>Context fields that make the joined events readable</h2><p>Join keys get you onto the right documents. Context fields usually exist on only one data source and add the detail you need to read those documents. We use several of them in the lab that follows.</p><h3>Context fields in Kubernetes audit logs</h3><p>Field</p><p>Why it matters</p><p><code>user.name</code> / <code>kubernetes.audit.user.username</code></p><p>Identifies the API principal (human user, service account, or system component)</p><p><code>kubernetes.audit.user.groups</code></p><p>Identifies group membership for the principal (for example service account groups)</p><p><code>user_agent.original</code></p><p>Shows which client made the request; unusual clients on a workload identity are often worth a closer look</p><p><code>kubernetes.audit.verb</code> + <code>objectRef.resource</code> / <code>objectRef.subresource</code></p><p>Describes what was attempted against which Kubernetes object type</p><p><code>kubernetes.audit.requestURI</code></p><p>Adds request detail beyond verb and objectRef; for exec, the decoded URI includes the command list</p><p><code>kubernetes.audit.requestObject.spec.*</code></p><p>Exposes the submitted object spec (security context, volumes, and similar) when you need to judge how sensitive a create or update was</p><p><code>source.ip</code> / <code>kubernetes.audit.sourceIPs</code></p><p>Shows where the API call came from (node, pod network, or external client)</p><p><code>event.outcome</code> / <code>kubernetes.audit.annotations.authorization_k8s_io/decision</code></p><p>Distinguishes successful/allowed versus failed/forbidden API calls via native K8s authorization</p><p><code>kubernetes.audit.responseStatus.reason</code></p><p>Describes the reason for a failed API request</p><h3>Context fields in Defend for Containers</h3><p>Field</p><p>Why it matters</p><p><code>process.name</code> and <code>process.args</code></p><p>Shows what’s executed inside the container and with which arguments; minimal images often use wrappers which put the executed process details in <code>process.args</code> (including the process name), so use both fields</p><p><code>process.interactive</code></p><p>Flags interactive sessions; often useful next to audit <code>pods/exec</code>, and used by some sequence joins</p><p><code>file.path</code></p><p>On file events, shows which path was touched (for example, a projected service account token or certificate authority [CA] file)</p><p><code>container.security_context.privileged</code></p><p>Shows whether the container ran privileged; useful to cross-check a sensitive audit pod create</p><p><code>orchestrator.resource.name</code> / <code>orchestrator.namespace</code></p><p>Tie the runtime event to a specific pod and namespace</p><p><code>host.name</code></p><p>Identifies which node the workload ran on</p><p><code>container.id</code> / <code>container.name</code></p><p>Narrow activity to a specific container when a pod has more than one</p><p><code>event.category</code> / <code>event.action</code></p><p>Point you at the right activity type (process versus file) and what operation occurred</p><h2>Lab scenario: Tracing a compromised service account from audit logs to runtime</h2><p>In our EKS lab, we ran a compromised workload service account through discovery, secret access, a privileged breakout create, exec, and cloud metadata probes. That traffic is attributed as an SA without the caller pod-name extra, so the following walkthrough uses the service-account / objectRef join and the context fields from above to move between Kubernetes audit and D4C.</p><h3>Finding a suspicious service account in Kubernetes audit logs</h3><p>We started on the K8s audit side, looking for workload identities whose clients didn’t look like normal controllers or app traffic. Most legitimate SA requests come from in-cluster components with familiar user agents. When a <code>system:serviceaccount:…</code> principal shows up with something like <code>curl</code> or <code>python-requests</code>, that can mean someone is driving the API with a stolen or projected token from a shell or a short script, rather than through the application’s usual client. That pattern doesn’t prove compromise on its own, but it gives us an identity and namespace to expand on. The same hunt works for other HTTP clients you may see on a stolen token (<code>axios</code>, <code>undici</code>, and <code>similar</code>). Treat <code>user_agent.original</code> as a lead, not proof. It’s easy to spoof. A curl session can send a legitimate-looking <code>kubectl</code> user agent, so a “normal” user agent doesn’t rule the identity out.</p><p>Using the audit context fields <code>user.name </code>and <code>user_agent.original</code>, we looked for SA principals (<code>system:serviceaccount:…</code>) paired with clients like <code>python-requests/…</code> or <code>curl/…</code>.</p>user.name: system\:serviceaccount\:* and
(user_agent.original: python-requests* or user_agent.original: curl/*)<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt755c05dcd645bc45/6a969b68f08ee146d385368f/image7.png" alt="Kubernetes audit logs field statistics showing a workload service account calling the API with curl and python-requests" /><p>We kept that service account and namespace for the rest of the example.</p><h3>Timelining a suspicious service account's API activity</h3><p>We timelined the SA and kept verb, object, user agent, authorization decision, and outcome in view:</p><p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0515430c47014cff/6a969b8f48c2993b86c69062/image12.png" alt="Compromised service account timeline in Kubernetes audit logs from recon to secret access, TokenRequest and pod create" /><p>Context fields did most of the work here. <code>user_agent.original</code> separated python-requests discovery from curl harvest. <code>event.outcome</code> separated forbidden recon from allowed secret gets. <code>objectRef.resource</code> / <code>subresource</code> showed TokenRequest (<code>serviceaccounts</code> + <code>token</code>) and later <code>pods</code> / <code>exec</code>.</p><p>From those same rows, we also collected pod names where <code>objectRef.resource</code> was pods. One name was the original workload pod already running with that SA (the foothold). A later <code>create</code> event named a second pod, which is the breakout that we explore next.</p><h3>Spotting the privileged pod create behind a container escape</h3><p>In the same timeline, a <code>kubernetes.audit.verb: create on objectRef.resource: pods</code> named a new breakout pod. The creation alone is interesting; the audit-only fields on <code>requestObject.spec</code> are what showed how sensitive it was. That document had <code>hostPID</code>, <code>hostIPC</code>, a privileged security context, and a <code>hostPath</code> mount to <code>/</code>, still attributed to the same workload SA and curl user agent that had been reading secrets.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f9c12a2c3f6a649/6a969bbfde239597ace83d4e/image8.png" alt="Privileged pod create in Kubernetes audit logs with hostPID, hostIPC and a hostPath mount to root in requestObject.spec" /><p>That same document also carried the pod create → use join into D4C. <code>objectRef.name</code> and <code>objectRef.namespace</code> are the pod and namespace we query on the runtime side next.</p><h3>Querying container runtime data with pod names from the audit timeline</h3><p>The service account timeline gave us two pod names: the foothold pod and the breakout pod. We queried Defend for Containers for both:</p>data_stream.dataset: "cloud_defend.process" and
orchestrator.namespace: "emu-satoken-0297d6" and
orchestrator.resource.name: ("worker-0297d6" or "breakout-0297d6")<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf1ece62c89abae65/6a969bebde2395f246e83d52/image3.png" alt="Container runtime process events for the foothold and breakout pods matched on orchestrator.resource.name" /><p>On the foothold pod, process context showed a projected-token read:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbb1e498cd27aecb2/6a969c0660f7950f5bd771b7/image11.png" alt="Foothold pod process event where process.args shows cat reading the projected service account token path" /><p>On the breakout pod, process context showed cloud instance-metadata clients were queried:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc6508a551423351b/6a969c2f893681b04e3ddb49/image4.png" alt="Breakout pod curl events querying AWS, Azure and Google cloud instance metadata endpoints" /><h3>Why nsenter and chroot never reach container runtime events</h3><p>On the breakout pod, we also ran a lab-safe host breakout attempt through <code>pods/exec: nsenter -t1 -m -u -n -i true</code> and <code>chroot /host true</code>. The <code>true</code> processes are no-ops, so the session doesn’t do anything destructive. In a real breakout, the same wrappers usually target a shell or follow-on tool, for example <code>nsenter … /bin/bash</code> or <code>chroot /host /bin/sh</code>.</p><p>We went back to the D4C process events for that breakout pod looking for <code>nsenter</code> and <code>chroot</code> next to the metadata activity. On runtime events, we read <code>process.name</code> and <code>process.args</code> together. Those wrapper names weren’t there. D4C showed <code>process.name: true</code> and <code>process.args: true</code> instead, matching the <code>true</code> targets in our lab commands. <code>nsenter</code> and <code>chroot</code> only set up the breakout and then hand off to that target. After the handoff, runtime records that target command, which here was <code>true</code>. Even with both fields, the wrappers never made it into D4C, so we turn to Kubernetes audit next.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt986ca2c64568d35d/6a969c6a92308256d0c4ac12/image5.png" alt="Container runtime process events showing true instead of the nsenter and chroot container escape wrappers" /><p>K8s audit and D4C answer different questions on the same breakout. The same SA’s <code>pods/exec</code> events carry the full command list in <code>kubernetes.audit.requestURI</code>. Decoding that URI showed <code>nsenter</code> and <code>chroot</code> against the breakout pod (the API-level breakout tools), while D4C showed what actually ran in the container after those wrappers and what that session did next.</p><p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1c0cd8956b1e4a7b/6a969c8ede23953124e83d56/image6.png" alt="Kubernetes audit logs with decoded pods/exec URIs revealing nsenter and chroot container escape commands" /><h2>Conclusion</h2><p>We’ve covered the core of unified container visibility: bridging Kubernetes audit logs with Defend for Containers telemetry. Plus, we’ve explored the two primary ways to join these datasets; that is, using pod-caller identity for direct attribution or service account and <code>objectRef</code> mapping for broader investigations. And we’ve demonstrated how context fields like <code>user_agent.original</code> or decoded <code>requestURI</code> parameters turn those joined events into clear, actionable attack timelines.</p><p>Kubernetes audit and D4C remain two halves of the same picture: the API on one side, what ran inside the container on the other. Know which fields actually join them and which one-sided context fields still change how you read an investigation. Two joins cover most cases: caller identity when the pod-name extra is on the audit event, and service account plus <code>objectRef</code> pod names when the call is attributed only as a service account. Fields such as <code>requestObject.spec</code>, a decoded exec <code>requestURI</code>, and <code>user_agent.original</code> won’t join the two data sources by themselves, but they’re often what makes the joined documents actionable.</p><h2>What next?</h2><p>Now that you have the mapping foundation, the best way to operationalize these techniques is to test them against your own environment's telemetry. Start by implementing the queries we walked through in our lab scenario to identify suspicious service account activity, and then pivot to D4C to verify the actual runtime impact. For a shortcut, explore our prebuilt rules tagged <code>Data Source: Elastic Defend for Containers</code> and <code>Data Source: Kubernetes</code>, which serve as ready-to-use examples of these join patterns in action.</p><p>You can browse the same detection content in the <a href="https://github.com/elastic/detection-rules">detection-rules</a> repository or our <a href="https://elastic.github.io/detection-rules-explorer/">rules explorer</a> page.</p>]]></content:encoded>
    <link>https://www.elastic.co/security-labs/threat-command/kubernetes-audit-logs-container-escape</link>
    <guid isPermaLink="false">kubernetes-audit-logs-container-escape</guid>
    <category><![CDATA[Detection Engineering]]></category>
    <dc:creator><![CDATA[Isai Anthony]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a9b5a1d6a281f9b/6a9698cf6fe1454090b1c811/image9.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 03 Sep 2026 15:19:21 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Now available: the 2025 State of Detection Engineering at Elastic]]></title>
    <description><![CDATA[The 2025 State of Detection Engineering at Elastic explores how we create, maintain, and assess our SIEM and EDR rulesets.]]></description>
    <content:encoded><![CDATA[<p>We’ve been working hard at Elastic Security Labs! We've just published a brand new report: <a href="https://www.elastic.co/resources/security/report/state-of-detection-engineering-at-elastic"><strong>the 2025 State of Detection Engineering at Elastic</strong></a>. This report gives readers an exclusive look into the work of developing and maintaining our pre-built <a href="https://elastic.github.io/detection-rules-explorer/">SIEM Detection</a> rules and <a href="https://github.com/elastic/protections-artifacts/tree/main/behavior">Endpoint Protection Behavior</a> rulesets. </p>
<p>In this report, you'll get an inside look at how we work to keep our users protected and gain valuable insights into the world of detection engineering, like:</p>
<ul>
<li>How we analyze real-world threats, like the CUPS vulnerability and Windows Local Privilege Escalation.  </li>
<li>Our robust rule development strategies, including automation and the <a href="https://www.elastic.co/security-labs/elastic-releases-debmm">Detection Engineering Behavioral Maturity Model (DEBMM)</a>.  </li>
<li>Enhancements to <a href="https://www.elastic.co/security">Elastic Security</a> through integration enrichments with AWS, Okta, and more.  </li>
<li>Our internal metrics and evaluation processes for ensuring rule effectiveness.  </li>
<li>Our partnership with the <a href="https://www.elastic.co/resources/security/report/global-threat-report">Elastic Global Threat Report</a> and our future plans, including AI threat detection.</li>
</ul>
<p>This report represents a full year of our detection engineering efforts, from October 2023 to October 2024. We chose this timeframe to capture our work following the 2023 Elastic Global Threat Report and gather enough data to identify meaningful patterns. </p>
<p>We collected and analyzed all the contextual data of an entire year’s worth of detection engineering efforts to build out the story of what we do and how we do it. Including Security Labs threat research publications, GitHub metadata from activity across our rules repos, alert telemetry, and operational metric data are used to both guide and assess our detection engineering efforts. We also conducted a series of interview-style conversations with the threat researchers, detection engineers, and developers behind the data. We wanted to dive-deep into the specifics and garner the details of the processes behind the outputs (detection rules, threat research articles, etc.) that our customers see. Then we put these details together to create a cohesive story that might benefit the larger community. </p>
<p>We’re pulling back the curtain on our detection engineering practices, going beyond the traditional survey-style State of Detection Engineering report. By revealing this information — information that security tool creators often keep private — we aim to demonstrate our commitment to our users and reinforce the fact that you are not alone in your security journey. We’re right here with you, every step of the way.     </p>
<h2 id="thediscussioncontinues">The discussion continues</h2>
<p>Elastic Security Labs is dedicated to providing in-depth research to the security community — whether you’re an Elastic customer or not. By sharing the details of how we manage and leverage the Elastic Security solution, we hope to spark a broader conversation around detection engineering and encourage the community to hold our work accountable. If you’re interested in a broader look at the report, you can check out the <a href="https://www.elastic.co/blog/state-of-detection-engineering-at-elastic-2025">blog on Elastic</a>. </p>
<p><a href="https://www.elastic.co/resources/security/report/state-of-detection-engineering-at-elastic">Download the free report</a>, and <a href="https://x.com/elasticseclabs">join the conversation</a>!</p>]]></content:encoded>
    <link>https://www.elastic.co/security-labs/reports/state-of-detection-engineering-at-elastic-2025</link>
    <guid isPermaLink="false">state-of-detection-engineering-at-elastic-2025</guid>
    <dc:creator><![CDATA[Isai Anthony,Mika Ayenson]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta937de99c63e5bfc/6a7d753afc63ab5d57649c4f/header.png" length="0" type="image/png"/>
    <pubDate>Thu, 24 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>