惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
月光博客
月光博客
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
人人都是产品经理
人人都是产品经理
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
有赞技术团队
有赞技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - Franky
The Cloudflare Blog
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
Jina AI
Jina AI
阮一峰的网络日志
阮一峰的网络日志
小众软件
小众软件
Last Week in AI
Last Week in AI

Elastic Security Labs

Agentic SOC alert triage: 60% to 92% AI accuracy — Elastic Security Labs Agentic SOC alert triage: 60% to 92% AI accuracy Entity definition, identity resolution and entity risk scoring — Elastic Security Labs Entity definition, identity resolution and entity risk scoring AI coding agent audit: Cursor hooks and Elastic Agent — Elastic Security Labs AI coding agent audit: Cursor hooks and Elastic Agent Coding agent security: Claude Code, tunnels and LaunchAgents — Elastic Security Labs npm cooldown removal detection with Elastic Agent and CEL — Elastic Security Labs npm cooldown removal detection with Elastic Agent and CEL Shai-Hulud strikes again: CHAINDROP worm hits 400+ npm packages — Elastic Security Labs AI vulnerability triage: Bug bounty reports at $2 each — Elastic Security Labs AI vulnerability triage: Bug bounty reports at $2 each Evaluating LLMs for SOC automation: a benchmark framework — Elastic Security Labs SOC case management and detection rule history — Elastic Security Labs SOC case management and detection rule history Elastic Security at Black Hat 2026: Alert Zero and agentic SOC Elastic Security at Black Hat 2026: Alert Zero and agentic SOC — Elastic Security Labs Alert Zero: Automate alert triage for the agentic SOC — Elastic Security Labs Elastic Defend: 800+ vulnerable driver YARA rules — Elastic Security Labs Alert Zero: Automate alert triage for the agentic SOC Elastic Defend: 800+ vulnerable driver YARA rules Hugging Face breach: GenAI detection with Elastic Defend — Elastic Security Labs Microsoft Sentinel detection rules: automatic migration to Elastic — Elastic Security Labs Microsoft Sentinel detection rules: automatic migration to Elastic AI agent optimization: how Elastic InfoSec cut LLM calls by 60% — Elastic Security Labs AI agent optimization: how Elastic InfoSec cut LLM calls by 60% Agentic SOC architecture: specialized agents cut costs 5.7× — Elastic Security Labs Agentic SOC architecture: specialized agents cut costs 5.7× ES|QL COMPLETION: LLM triage for noisy detection rules — Elastic Security Labs wp2shell: detecting WordPress pre-auth RCE end-to-end — Elastic Security Labs
ES|QL COMPLETION: LLM triage for noisy detection rules
Aaron Jewitt · 2026-07-23 · via Elastic Security Labs

We ran a noisy wget detection rule on Elastic's own cloud fleet for seven days. Three destinations survived deterministic filtering, Elasticsearch Query Language (ES|QL) COMPLETION triaged all three, and none of them created an alert that an analyst had to open. Each rule parses the destination from curl and wget executions, filters known-good hosts, redacts secrets, and then hands whatever’s left to a large language model (LLM) for a triage verdict. File transfer detections stay on in cloud environments without burying the queue in package downloads and continuous integration (CI) jobs.

This post builds on Beyond Behaviors: AI-Augmented Detection Engineering with ES|QL COMPLETION, which showed how COMPLETION can reason over an aggregate of multiple alerts tied to one entity. The pattern here is a little different. We use COMPLETION inside individual noisy detection rules, before an alert reaches an analyst, to decide whether a surviving curl or wget event is likely attacker tradecraft, expected automation, or worth a closer look.

At Elastic, our InfoSec team operates as Customer Zero. That is, we run the newest versions of Elastic Security in our production environment, often before they’re released publicly. Our fleet spans thousands of laptops, servers, and cloud workloads across a globally distributed workforce. We’re the first and most demanding user of every feature we ship, including ES|QL COMPLETION. This work happened in June 2026, while we were tuning two Elastic Security detection rules on Elastic Cloud Serverless.

Why curl and wget rules are noisy in cloud environments

Attackers often transfer tools or payloads after they compromise a host. MITRE ATT&CK maps this behavior to Ingress Tool Transfer, T1105 and explicitly calls out curl and wget as common Linux utilities for moving files into a victim environment. In a cloud environment, that makes these binaries worth watching.

The hard part isn’t writing the first rule; it’s keeping the rule useful after the first week.

Cloud hosts lean on curl and wget constantly, whether they’re used to pull packages, retrieve build artifacts, or handle basic setup tasks. CI workers grab the outputs they need, and Kubernetes jobs call metadata endpoints. Infrastructure tools request configuration from their sources, and security scanners test reachable services. Every one of those can look like "a process downloaded something from the internet" if the rule only looks at the binary name and URL.

You can measure this in your own environment before you enable anything. This ES|QL query parses the destination host out of every curl and wget execution and ranks destinations by volume, so you can see what a name-and-URL-only rule would surface across your fleet:


The destinations at the top of that list are your best allow-list candidates: high-volume, stable, and clearly known-good. The long tail is where LLM triage earns its place: destinations too infrequent or too varied to be worth a hand-written exception but still worth a look before they reach an analyst.

Traditional tuning addresses this with exceptions:

  • Allow this package mirror.
  • Allow this internal service.
  • Allow this CI parent process.
  • Allow this cloud metadata endpoint.
  • Allow this one-off bootstrap script.

Deterministic filters are cheap, explainable, and repeatable. But the exception list grows every time the environment changes. For curl and wget, that growth is constant.

Note: These rules, and the query above, depend on process execution events from your cloud hosts and containers. You can collect this data with Elastic Defend or with Auditbeat. Our cloud fleet collects the data with Auditbeat, which can use the add_session_metadata processor that can use eBPF or kprobes to enrich the full process lineage, including the session leader and group leader. We use this information to filter noisy automation by its process ancestry rather than by command line alone. If you run containerized workloads, deploy it as a DaemonSet. (See Running Auditbeat on Kubernetes.)

How ES|QL COMPLETION filters curl and wget events

The curl and wget ES|QL COMPLETION triage rules follow the same structure. They’re additive companions to existing deterministic rules, not replacements. The original rules remain enabled, while the LLM-triage versions focus on the events that survive the known-good filters.

The flow is intentionally conservative:

  1. Select Linux process execution events where process.name is curl or wget.
  2. Build a normalized argument string from process.args.
  3. Parse a destination host from a schema://host URL.
  4. Drop events without a parsed destination.
  5. Apply deterministic allow-lists for known package repositories, metadata endpoints, internal services, and expected automation.
  6. Redact credentials and tokens from the command line.
  7. Aggregate by host and destination.
  8. Cap the rows sent to COMPLETION.
  9. Ask the LLM for a structured verdict.
  10. Alert only on TP or SUSPICIOUS results with confidence above 0.7.

Here’s a generic version of that shape. Your own rule should split curl and wget if they need different allow-lists, but the core approach is the same.


Notes:

  • ES|QL COMPLETION is generally available on Elastic Cloud Serverless and in Elastic Stack 9.3 and later. It was in technical preview in 9.1 and 9.2 and isn’t available before 9.1.
  • The ES|QL COMPLETION command sends one request to the configured LLM endpoint for each row it processes. The command has a default row limit of 100, and you should still use selective WHERE clauses and an explicit LIMIT before COMPLETION to control cost.
  • COMPLETION requires an inference endpoint configured with the completion task type. In the example above, replace my-completion-inference-endpoint with the inference endpoint ID configured for your Elastic environment.

Why detection rules should filter by parsed destination, not raw command line

One of the most useful changes in these rules is where the allow-list runs. Instead of matching every exception against the raw command line, the wget rule parses the URL host into dest_host and anchors its allow-list to that parsed field. This is the pattern we recommend.

Anchoring filters to the parsed destination matters because raw argument filters are easy to make brittle. A substring match can accidentally allow a command because the expected domain appears in a parameter, a path, or a misleading string. Parsing the destination first gives the rule a narrower question: What host did this command try to reach?

This is an example of using the dest_host value to filter out known destinations in your environment:


Redact secrets from curl and wget command lines before the LLM sees them

Command lines often contain secrets. curl and wget make this worse because headers, tokens, signed URLs, basic-auth credentials, and proxy usernames can all appear in process arguments.

The rules redact known secret patterns before aggregation and before COMPLETION runs. This includes authorization headers, bearer tokens, API keys, query string secrets, URL embedded credentials, user/password flags, and JSON Web Tokens (JWTs).


Warning: These patterns cover common secret formats but not all of them. Treat them as a starting point, and review what actually reaches the model. Command text leaves your environment when COMPLETION calls the inference endpoint, so keep that endpoint within your trust boundary and redact before, not after, the model sees the row.

Redaction protects sensitive data. It also improves the quality of the prompt. The LLM doesn’t need the token value to decide whether a command is suspicious. It needs the destination, parent process, execution context, and command shape.

Preventing prompt injection from attacker-controlled command line strings

The prompt includes a constraint that’s easy to skip and important to keep:


Command lines can contain attacker-controlled strings. A downloaded URL, path, parameter, or shell fragment could include text that looks like an instruction to the model. The rule should never allow those strings to steer the model outside the triage task.

The prompt also tells the model not to assume benign intent from words like test, dev, admin, ci, automation, or internal. Those words appear in legitimate commands, but attackers can use them, too. The LLM should consider them as weak context, not proof.

How to parse and filter ES|QL COMPLETION verdicts by confidence

The LLM response is deliberately constrained to one line:


That format lets ES|QL parse the response and keep the rule decision visible in alert fields:


For our internal rules, FP results don’t create alerts. SUSPICIOUS results map to low severity, while TP results retain the rule's medium severity. Both rules suppress duplicate alerts for six hours by (host, destination) so one noisy host doesn’t repeatedly alert on the same destination, consuming tokens.

The alert note tells analysts to start with the LLM output and then verify it. That order matters. The model gives a triage recommendation, not a final incident response decision. Analysts still review the destination, sampled commands, parent processes, user context, and surrounding process tree before closing or escalating.

ES|QL COMPLETION test results: wget rule over seven days

Before enabling the wget rule, we tested the full pipeline in a quality assurance (QA) Discover session over a seven-day window. We kept the final FP, TP, or SUSPICIOUS filter out of the testing query so we could see every model verdict.

Only three destinations survived the deterministic filters in that window, and all three came from the QA environment:

DestinationLLM verdictResult
cdn.playwright.devFPExpected Playwright CI activity
1.1.1.1FPDNS over HTTPS activity
18.66.X.XSUSPICIOUSSuspicious due to the destination being an internal AWS IP, but not considered a TP without other context from the command line

Two of these wouldn’t have created an alert, and one would have created a low- severity alert due to the suspicious verdict. You can adjust the prompt and filters as needed for your environment. For example, if you manage your own DNS servers, a connection to a public DNS via HTTPs should be treated as suspicious.

This was a useful outcome for two reasons. First, it proved that COMPLETION, redaction, parsing, and DISSECT all worked end to end. Second, it showed why the LLM should run after deterministic filtering, not before it. There’s no reason to spend tokens on package mirrors, known automation, or low-value QA noise when ES|QL can remove those rows first.

LLM triage works best for noisy rules where the underlying behavior is still worth detecting. curl and wget fit that profile because downloading a payload to a cloud host is common attacker behavior, but the same utilities are also common in normal operations.

Good candidates usually have four traits:

  1. The behavior has clear security value, such as file transfer, script execution, credential access, or unusual network activity.
  2. Deterministic filters remove the obvious false positives but still leave ambiguous events.
  3. The event contains enough context for triage, such as destination, command line, parent process, user, host, and count.
  4. The rule can cap COMPLETION rows before calling the LLM.

Poor candidates are the opposite. If the rule has no useful context, no stable grouping key, or no way to control row count, start with the deterministic rule design first. LLM triage shouldn’t rescue an under-specified query.

Why LLM triage keeps noisy detection rules trustworthy

The main lesson is simple: Use deterministic logic for what you already know, and reserve LLM reasoning for the cases that remain ambiguous. For curl and wget, that means parsing the destination, applying known-good filters, redacting sensitive values, aggregating by host and destination, and only then asking COMPLETION for a structured triage verdict.

This gives detection engineers a practical way to keep noisy but important rules enabled in cloud environments. Consider the three destinations from our seven-day test. Without LLM triage, each one is an alert an analyst has to open, investigate, and close as a false positive. Most are obvious at a glance, but every one of those glances teaches the analyst that this rule means routine admin activity.

The real cost of a noisy rule is eroded trust. Analysts stop taking it seriously, and a genuine ingress tool transfer gets the same reflexive close as a package download. By letting COMPLETION clear the easy false positives, we keep those interruptions out of the queue and protect the analyst's trust in the alert for the times it fires on something that isn’t routine.

The same COMPLETION technique works far beyond curl and wget. Any noisy rule where the behavior is worth detecting but most matches are benign is a candidate, whether that’s credential access, unusual outbound connections, or suspicious child processes. The shape stays the same: Filter deterministically, aggregate the survivors, and let an LLM separate the routine activity from the events an analyst should actually see. That’s the real value here, using the LLM as a filter for benign activity before it ever reaches the queue.

You don’t have to build these rules from scratch. We’ve published prebuilt versions of all four rules in the elastic/detection-rules repository, covering curl and wget with variants for Elastic Defend and Auditd data sources. If you’re running Elastic Stack 9.3 or later, you can install them from the prebuilt rules page in Elastic Security, point them at your completion inference endpoint, and adjust the allow-lists to fit your environment. If you want to review the rule logic first, the full ES|QL source for each rule is on GitHub: LLM-Based Curl Activity Triage, LLM-Based Curl Activity Triage via Auditd, LLM-Based Wget Activity Triage, and LLM-Based Wget Activity Triage via Auditd.