Detection rules › Elastic

GenAI or MCP Server Child Process Execution

Status
production
Kind
building block (feeds higher-level correlation rules; not a standalone alert)
Severity
low
Time window
119m
Author
Elastic
Source
github.com/elastic/detection-rules

Detects child process execution from GenAI tools or MCP (Model Context Protocol) servers. Adversaries exploit AI agents to execute system commands, exfiltrate data, or establish persistence. MCP servers provide LLMs direct access to execute shell commands, read files, and interact with external services. This building block provides visibility into AI-initiated process execution for correlation with other suspicious activity.

MITRE ATT&CK coverage

MITRE ATLAS coverage

Adversarial-ML threat framework (not MITRE ATT&CK).

Rule body elastic

[metadata]
creation_date = "2025/12/04"
integration = ["endpoint", "windows", "sentinel_one_cloud_funnel", "m365_defender"]
maturity = "production"
updated_date = "2026/04/21"

[rule]
author = ["Elastic"]
building_block_type = "default"
description = """
Detects child process execution from GenAI tools or MCP (Model Context Protocol) servers. Adversaries exploit AI agents
to execute system commands, exfiltrate data, or establish persistence. MCP servers provide LLMs direct access to execute
shell commands, read files, and interact with external services. This building block provides visibility into
AI-initiated process execution for correlation with other suspicious activity.
"""
from = "now-119m"
index = [
    "logs-endpoint.events.process-*",
    "logs-windows.sysmon_operational-*",
    "logs-m365_defender.event-*",
    "logs-sentinel_one_cloud_funnel.*",
]
interval = "60m"
language = "eql"
license = "Elastic License v2"
name = "GenAI or MCP Server Child Process Execution"
risk_score = 21
rule_id = "b2c3d4e5-f6a7-8901-bcde-f23456789012"
severity = "low"
tags = [
    "Domain: Endpoint",
    "OS: Linux",
    "OS: macOS",
    "OS: Windows",
    "Use Case: Threat Detection",
    "Tactic: Execution",
    "Data Source: Elastic Defend",
    "Data Source: Sysmon",
    "Data Source: Microsoft Defender XDR",
    "Data Source: SentinelOne",
    "Rule Type: BBR",
    "Domain: LLM",
    "Mitre Atlas: T0053",
]
timestamp_override = "event.ingested"
type = "eql"

query = '''
process where event.type == "start" 
  and (
    // GenAI clients
    process.parent.name in (
      "Cursor", "Cursor.exe", "cursor",
      "Cursor Helper", "Cursor Helper (Plugin)", "Cursor Helper (GPU)", "Cursor Helper (Renderer)",
      "Claude", "Claude.exe", "claude",
      "Claude Helper", "Claude Helper (Plugin)", "Claude Helper (GPU)", "Claude Helper (Renderer)",
      "Windsurf", "Windsurf.exe", "windsurf",
      "Windsurf Helper", "Windsurf Helper (Plugin)", "Windsurf Helper (GPU)", "Windsurf Helper (Renderer)",
      "Code", "Code.exe", "code",
      "Code Helper", "Code Helper (Plugin)", "Code Helper (GPU)", "Code Helper (Renderer)",
      "codex", "codex.exe",
      "Copilot", "Copilot.exe", "copilot",
      "Jan", "Jan.exe", "jan",
      "Jan Helper", "Jan Helper (Plugin)", "Jan Helper (GPU)", "Jan Helper (Renderer)",
      "LM Studio", "LM Studio.exe", "lmstudio",
      "Ollama", "Ollama.exe", "ollama",
      "GPT4All", "gpt4all", "gpt4all.exe",
      "textgen.exe", "textgen", "text-generation-webui.exe", "oobabooga.exe",
      "gemini-cli.exe", "gemini-cli",
      "genaiscript.exe", "genaiscript",
      "grok.exe", "grok",
      "qwen.exe", "qwen",
      "koboldcpp.exe", "koboldcpp", "KoboldCpp",
      "llama-server", "llama-cli",
      "OpenClaw", "openclaw", "openclaw.exe",
      "Moltbot", "moltbot", "moltbot.exe",
      "Clawdbot", "clawdbot", "clawdbot.exe"
    ) or
    // OpenClaw/Moltbot/Clawdbot via Node.js
    (process.parent.name in ("node", "node.exe") and
     process.parent.command_line like~ ("*openclaw*", "*moltbot*", "*clawdbot*")) or
    // Package managers running MCP servers
    (process.parent.name in ("npx", "npx.exe", "pnpm", "pnpm.exe", "yarn", "yarn.exe", "bunx", "bunx.exe") and
     process.parent.command_line like~ ("*@modelcontextprotocol/*", "*mcp-server-*", "*mcp_server*")) or
    
    // Node/Deno/Bun running MCP servers
    (process.parent.name in ("node", "node.exe", "deno", "deno.exe", "bun", "bun.exe") and
     process.parent.command_line like~ ("*@modelcontextprotocol/*", "*mcp-server-*", "*mcp_server*")) or
    
    // Python MCP servers
    (process.parent.name like~ "python*" and
     process.parent.command_line like~ ("*-m mcp_server*", "*mcp-server-*", "*mcp_server*")) or
    
    // MCP server binaries
    process.parent.name like~ ("mcp-server*", "*-mcp-server", "*_mcp_server*") or
    process.parent.name in ("mcp-server", "mcp-server-elastic-cloud", "github-mcp-server")
  )
  and process.name != null
  // Exclusions
  and not (
    // Runtime self-spawns
    (process.parent.name in ("node", "node.exe") and process.name in ("node", "node.exe")) or
    (process.parent.name like~ "python*" and process.name like~ "python*") or
    (process.parent.name in ("deno", "deno.exe") and process.name in ("deno", "deno.exe")) or
    (process.parent.name in ("bun", "bun.exe") and process.name in ("bun", "bun.exe")) or
    
    // Helper process self-spawns
    (process.parent.name == "Cursor" and process.name like~ "Cursor Helper*") or
    (process.parent.name == "Claude" and process.name like~ "Claude Helper*") or
    (process.parent.name == "Windsurf" and process.name like~ "Windsurf Helper*") or
    (process.parent.name == "Code" and process.name like~ "Code Helper*") or
    (process.parent.name == "Jan" and process.name like~ "Jan Helper*") or
    (process.parent.name == "LM Studio" and process.name like~ "LM Studio Helper*") or
    (process.parent.name == "Ollama" and process.name like~ "Ollama Helper*") or
    
    // docker
    (process.name in ("docker", "docker.exe") and process.args == "context" and process.args == "ls") or
    // neighbor / arp / ps / which (args tokens or full /bin/sh -c)
    (
      process.args in (
        "ip neigh show",
        "arp -a -n -l",
        "ip neighbor show dev wlan0",
        "ip neighbor show dev eth0",
        "arp -a | findstr /C:---"
      ) or
      process.command_line in (
        "/bin/sh -c ip neigh show",
        "/bin/sh -c arp -a -n -l",
        "/bin/sh -c /bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=",
        "/bin/sh -c which ps"
      )
    ) or
    // git
    (process.name in ("git", "git.exe") and (
      (process.args == "remote" and process.args == "get-url" and process.args == "origin") or
      (process.args == "symbolic-ref" and process.args == "refs/remotes/origin/HEAD" and process.args == "--short") or
      (process.args == "rev-parse" and process.args == "--abbrev-ref" and process.args == "HEAD") or
      (process.args == "status" and process.args == "-z" and process.args == "-uall") or
      (process.args == "config" and process.args == "--get" and process.args == "commit.template") or
      (process.args == "config" and process.args == "user.email") or
      (process.args == "rev-parse" and process.args == "--show-toplevel")
    )) or
    // version / help
    process.args in ("--version", "--help", "-v", "-h", "-V", "version", "help")
  )
'''


[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"


[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"

Stages and Predicates

Stage 1: process

process where event.type == "start"
  and (
    process.parent.name in (
      "Cursor", "Cursor.exe", "cursor",
      "Cursor Helper", "Cursor Helper (Plugin)", "Cursor Helper (GPU)", "Cursor Helper (Renderer)",
      "Claude", "Claude.exe", "claude",
      "Claude Helper", "Claude Helper (Plugin)", "Claude Helper (GPU)", "Claude Helper (Renderer)",
      "Windsurf", "Windsurf.exe", "windsurf",
      "Windsurf Helper", "Windsurf Helper (Plugin)", "Windsurf Helper (GPU)", "Windsurf Helper (Renderer)",
      "Code", "Code.exe", "code",
      "Code Helper", "Code Helper (Plugin)", "Code Helper (GPU)", "Code Helper (Renderer)",
      "codex", "codex.exe",
      "Copilot", "Copilot.exe", "copilot",
      "Jan", "Jan.exe", "jan",
      "Jan Helper", "Jan Helper (Plugin)", "Jan Helper (GPU)", "Jan Helper (Renderer)",
      "LM Studio", "LM Studio.exe", "lmstudio",
      "Ollama", "Ollama.exe", "ollama",
      "GPT4All", "gpt4all", "gpt4all.exe",
      "textgen.exe", "textgen", "text-generation-webui.exe", "oobabooga.exe",
      "gemini-cli.exe", "gemini-cli",
      "genaiscript.exe", "genaiscript",
      "grok.exe", "grok",
      "qwen.exe", "qwen",
      "koboldcpp.exe", "koboldcpp", "KoboldCpp",
      "llama-server", "llama-cli",
      "OpenClaw", "openclaw", "openclaw.exe",
      "Moltbot", "moltbot", "moltbot.exe",
      "Clawdbot", "clawdbot", "clawdbot.exe"
    ) or
    (process.parent.name in ("node", "node.exe") and
     process.parent.command_line like~ ("*openclaw*", "*moltbot*", "*clawdbot*")) or
    (process.parent.name in ("npx", "npx.exe", "pnpm", "pnpm.exe", "yarn", "yarn.exe", "bunx", "bunx.exe") and
     process.parent.command_line like~ ("*@modelcontextprotocol/*", "*mcp-server-*", "*mcp_server*")) or
    (process.parent.name in ("node", "node.exe", "deno", "deno.exe", "bun", "bun.exe") and
     process.parent.command_line like~ ("*@modelcontextprotocol/*", "*mcp-server-*", "*mcp_server*")) or
    (process.parent.name like~ "python*" and
     process.parent.command_line like~ ("*-m mcp_server*", "*mcp-server-*", "*mcp_server*")) or
    process.parent.name like~ ("mcp-server*", "*-mcp-server", "*_mcp_server*") or
    process.parent.name in ("mcp-server", "mcp-server-elastic-cloud", "github-mcp-server")
  )
  and process.name != null
  and not (
    (process.parent.name in ("node", "node.exe") and process.name in ("node", "node.exe")) or
    (process.parent.name like~ "python*" and process.name like~ "python*") or
    (process.parent.name in ("deno", "deno.exe") and process.name in ("deno", "deno.exe")) or
    (process.parent.name in ("bun", "bun.exe") and process.name in ("bun", "bun.exe")) or
    (process.parent.name == "Cursor" and process.name like~ "Cursor Helper*") or
    (process.parent.name == "Claude" and process.name like~ "Claude Helper*") or
    (process.parent.name == "Windsurf" and process.name like~ "Windsurf Helper*") or
    (process.parent.name == "Code" and process.name like~ "Code Helper*") or
    (process.parent.name == "Jan" and process.name like~ "Jan Helper*") or
    (process.parent.name == "LM Studio" and process.name like~ "LM Studio Helper*") or
    (process.parent.name == "Ollama" and process.name like~ "Ollama Helper*") or
    (process.name in ("docker", "docker.exe") and process.args == "context" and process.args == "ls") or
    (
      process.args in (
        "ip neigh show",
        "arp -a -n -l",
        "ip neighbor show dev wlan0",
        "ip neighbor show dev eth0",
        "arp -a | findstr /C:---"
      ) or
      process.command_line in (
        "/bin/sh -c ip neigh show",
        "/bin/sh -c arp -a -n -l",
        "/bin/sh -c /bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=",
        "/bin/sh -c which ps"
      )
    ) or
    (process.name in ("git", "git.exe") and (
      (process.args == "remote" and process.args == "get-url" and process.args == "origin") or
      (process.args == "symbolic-ref" and process.args == "refs/remotes/origin/HEAD" and process.args == "--short") or
      (process.args == "rev-parse" and process.args == "--abbrev-ref" and process.args == "HEAD") or
      (process.args == "status" and process.args == "-z" and process.args == "-uall") or
      (process.args == "config" and process.args == "--get" and process.args == "commit.template") or
      (process.args == "config" and process.args == "user.email") or
      (process.args == "rev-parse" and process.args == "--show-toplevel")
    )) or
    process.args in ("--version", "--help", "-v", "-h", "-V", "version", "help")
  )

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
process.argseq--abbrev-ref
process.argseqHEAD
process.argseqrev-parse
process.argseq--get
process.argseqcommit.template
process.argseqconfig
process.argseq--short
process.argseqrefs/remotes/origin/HEAD
process.argseqsymbolic-ref
process.argseq--show-toplevel
process.argseqrev-parse
process.argseq-uall
process.argseq-z
process.argseqstatus
process.argseqconfig
process.argsequser.email
process.argseqget-url
process.argseqorigin
process.argseqremote
process.nameingit, git.exe
process.argseqcontext
process.argseqls
process.nameindocker, docker.exe
process.nameinbun, bun.exe
process.parent.nameinbun, bun.exe
process.nameindeno, deno.exe
process.parent.nameindeno, deno.exe
process.nameinnode, node.exe
process.parent.nameinnode, node.exe
process.namestarts_withClaude Helper
process.parent.nameeqClaude
process.namestarts_withCode Helper
process.parent.nameeqCode
process.namestarts_withCursor Helper
process.parent.nameeqCursor
process.namestarts_withJan Helper
process.parent.nameeqJan
process.namestarts_withLM Studio Helper
process.parent.nameeqLM Studio
process.namestarts_withOllama Helper
process.parent.nameeqOllama
process.namestarts_withWindsurf Helper
process.parent.nameeqWindsurf
process.namestarts_withpython
process.parent.namestarts_withpython
process.argsin--help, --version, -h, -v, help, version
process.argsinarp -a -n -l, arp -a | findstr /C:---, ip neigh show, ip neighbor show dev eth0, ip neighbor show dev wlan0
process.command_linein/bin/sh -c /bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=, /bin/sh -c arp -a -n -l, /bin/sh -c ip neigh show, /bin/sh -c which ps

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
event.typeeq
  • start corpus 606 (elastic 606)
process.nameis_not_null
  • (no value, null check)
process.parent.command_linewildcard
  • *-m mcp_server*
  • *@modelcontextprotocol/*
  • *clawdbot* corpus 2 (elastic 2)
  • *mcp-server-*
  • *mcp_server*
  • *moltbot* corpus 2 (elastic 2)
  • *openclaw* corpus 2 (elastic 2)
process.parent.namein
  • Claude
  • Claude Helper
  • Claude Helper (GPU)
  • Claude Helper (Plugin)
  • Claude Helper (Renderer)
  • Claude.exe
  • Clawdbot
  • Code
  • Code Helper
  • Code Helper (GPU)
  • Code Helper (Plugin)
  • Code Helper (Renderer)
  • Code.exe
  • Copilot
  • Copilot.exe
  • Cursor
  • Cursor Helper
  • Cursor Helper (GPU)
  • Cursor Helper (Plugin)
  • Cursor Helper (Renderer)
  • Cursor.exe
  • GPT4All
  • Jan
  • Jan Helper
  • Jan Helper (GPU)
  • Jan Helper (Plugin)
  • Jan Helper (Renderer)
  • Jan.exe
  • LM Studio
  • LM Studio.exe
  • Moltbot
  • Ollama
  • Ollama.exe
  • OpenClaw
  • Windsurf
  • Windsurf Helper
  • Windsurf Helper (GPU)
  • Windsurf Helper (Plugin)
  • Windsurf Helper (Renderer)
  • Windsurf.exe
  • bun
  • bun.exe
  • bunx
  • bunx.exe
  • clawdbot.exe
  • codex
  • codex.exe
  • deno
  • deno.exe
  • gemini-cli
  • gemini-cli.exe
  • genaiscript
  • genaiscript.exe
  • github-mcp-server
  • gpt4all.exe
  • grok
  • grok.exe
  • koboldcpp
  • koboldcpp.exe
  • llama-cli
  • llama-server
  • lmstudio
  • mcp-server
  • mcp-server-elastic-cloud
  • moltbot.exe
  • node corpus 5 (elastic 4, splunk 1)
  • node.exe corpus 3 (elastic 2, splunk 1)
  • npx
  • npx.exe
  • oobabooga.exe
  • openclaw.exe
  • pnpm
  • pnpm.exe
  • qwen
  • qwen.exe
  • text-generation-webui.exe
  • textgen
  • textgen.exe
  • yarn
  • yarn.exe
process.parent.namewildcard
  • *-mcp-server
  • *_mcp_server*
  • mcp-server*
  • python* corpus 12 (elastic 12)