← All hunts medium TLP:CLEAR

AI Coding Agent Tool-Call Auditing

An AI agent operating under developer credentials is executing rare shell commands, accessing sensitive configuration files, or communicating with third-party MCP servers without explicit developer intent.

Based on research by Elastic Security Labs 2026-09-20 12 steps · 5 queries T1059 T1059.001 T1090.003

Brief

Why This Hunt

AI coding agents act as automated operators on the endpoint. They often execute commands and access files within the developer's user context, which can mask malicious activity. This hunt follows the research published by Elastic Security Labs in 13 million tool calls: auditing every AI coding agent action with Elastic Agent. As these agents gain the ability to call tools and modify environments, defenders need a flight-recorder audit to reconstruct agent intent.

How the Hunt Flows

The hunt begins by scoping the estate. The first query identifies every host running the Cursor IDE or its headless agent through software inventory surfaces. This defines the boundaries for subsequent behavioral analysis.

Next, the hunt examines process activity in two parallel streams. The first stream establishes a timeline of agent launches. The second stream baselines shell commands spawned by the agent. By stack-counting these commands across the fleet, the hunt highlights rare outliers, such as unexpected curl commands or local discovery scripts that deviate from the standard development lifecycle.

If rare commands appear, the hunt pivots to impact analysis. It queries file activity for access to sensitive paths like SSH keys, .env files, or git configurations. Simultaneously, it audits network connections to identify outbound traffic to non-standard ports or external hostnames that might represent rogue MCP server communication.

An analyst then reviews the consolidated findings. They determine if the combination of rare shell execution and sensitive file access constitutes a legitimate developer task or a malicious steering event.

Blind Spots

This hunt has two primary limitations. First, it lacks the "why" behind an action if the host does not have local hook telemetry enabled. While we see the shell command, we cannot see the model's internal reasoning without the tool-call logs described in the source research. Second, Cursor only loads hook configurations at startup. Hosts that have not restarted since a policy change will appear compliant but will not generate the necessary telemetry.

Steps

  1. Scope Cursor installations

    Query · scoping

    Identify hosts where Cursor or its headless agent is installed to define the hunt's scope.

    reads hb_software_inventorysql
    SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE LOWER(package_name) LIKE '%cursor%'

    What a hit looks like. A list of hosts with the AI agent installed. Silence indicates no managed installations are visible.

  2. Cursor agent process launches

    Query · detection candidate

    Detect the primary IDE and headless agent execution to establish session timelines.

    reads hb_process_activitysql
    SELECT device_hostname, process_name, process_cmd_line, user_name, time FROM hb_process_activity WHERE (LOWER(process_name) LIKE '%cursor%' OR LOWER(process_name) LIKE '%cursor-agent%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Process events for the Cursor binary. Frequent launches of the CLI agent may indicate automation or scripting.

  3. Rare agent-triggered shell commands

    Query · baseline

    Stack-count shell commands spawned by Cursor to identify outliers. Includes the parent command line to provide context on the tool call that initiated the shell.

    reads hb_process_activitysql
    SELECT process_cmd_line, parent_process_cmd_line, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE (LOWER(parent_process_name) LIKE '%cursor%' OR LOWER(parent_process_name) LIKE '%cursor-agent%') AND (LOWER(process_name) LIKE '%sh' OR LOWER(process_name) LIKE '%cmd.exe' OR LOWER(process_name) LIKE '%powershell%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_cmd_line, parent_process_cmd_line HAVING host_count <= 3 ORDER BY host_count ASC

    What a hit looks like. Shell commands seen on very few hosts. This highlights rare scripts or network-interactive commands like curl.

  4. Early stage triage

    Agent triage

    Assess whether the identified shell commands and session patterns justify a deeper investigation into file and network impact.

  5. Sensitive file access by agent

    Query · enrichment

    Detect Cursor or its sub-processes reading sensitive configuration or credential files. Note: the current instr() logic performs an exact filename match against the list; it does not match partial extensions unless the full filename matches.

    reads hb_file_activitysql
    SELECT device_hostname, process_name, file_path, file_name, time FROM hb_file_activity WHERE (LOWER(process_name) LIKE '%cursor%' OR LOWER(parent_process_name) LIKE '%cursor%') AND instr(',' || '{{sensitive_extensions}}' || ',', ',' || LOWER(file_name) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. File read events for credential-related filenames. Multiple hits on one host suggest an agent performing wide-scale credential discovery.

  6. Agent network connections

    Query · enrichment

    Identify outbound connections from Cursor that represent potential MCP server communication. Hostname is used to identify high-fidelity third-party server indicators.

    reads hb_network_connectionsql
    SELECT device_hostname, process_name, dst_endpoint_hostname, dst_endpoint_ip, dst_endpoint_port, direction, time FROM hb_network_connection WHERE (LOWER(process_name) LIKE '%cursor%' OR LOWER(process_path) LIKE '%cursor%') AND direction = 'outbound' AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Connections to external IPs and hostnames. Connections to non-standard HTTP ports (e.g. 8080, 5000) may indicate third-party MCP servers.

  7. Final agent triage

    Agent triage

    Synthesize the early session data with the file and network findings to determine if the agent was steered maliciously.

  8. Route on risk

    Decision

    Direct the workflow based on the agent's consolidated risk assessment.

  9. Isolate affected host

    Response action

    Contain potential exfiltration or malicious script execution by isolating the host.

  10. Forensic review of agent intent

    Analyst task

    Verify if the agent's actions were driven by a poisoned project file or malicious prompt context.

  11. Close out hunt

    Analyst task

    Finalize the investigation and document any tuning needs.

Coverage

Scenario coverage

StageCoveredHow, or why not
AI Agent Session Initiation
T1059
Yes cursor-agent-launches
AI Agent Shell Execution
T1059 · T1059.001
Yes rare-agent-shell-commands
AI Agent File Read and Edit
T1059
Yes sensitive-file-access
AI Agent MCP Tool Communication
T1090.003
Yes mcp-network-traffic

Blind spots

  • Needs The log-tool-calls.sh script to be active on the host. Without local hook telemetry, we see the 'what' (shell command) but not the 'why' (AI context), making it impossible to distinguish between developer steering and model hallucination. It would answer What was the specific model-assigned task that led to this command?. Remediation: Deploy the Elastic Agent hook script via MDM.
  • Needs A restart of the Cursor application after hook deployment. Cursor only reads hook configuration at startup; hosts that have not restarted will contribute no hook logs despite being 'compliant' in MDM. It would answer Are hosts showing 'green' on deployment actually collecting hooks?. Remediation: Prompt users to restart Cursor after the hook deployment script finishes.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
lookback_daysnumber14Days of history to examine.
scope_hostslist[host]Specific hostnames to focus on; leave empty for all hosts.
sensitive_extensionslist[string].pem, .key, .env, id_rsa, credentials, .git/config, .npmrc, .bash_historyFile names or extensions indicative of sensitive material.

Telemetry

SourceCategoryTelemetry
Endpoint telemetry (hb_ surfaces)endpointendpoint
Network telemetrynetworknetwork

Source

Download hunt.md Definition (JSON) An open hunt.md file; it runs anywhere that reads the format.
---
analysis: A standard rule can detect shell execution from a specific parent, but only
  a hunt can baseline the prevalence of those commands across the fleet and correlate
  them with sensitive file access and outbound MCP traffic to verify the agent's intent.
blind_spots:
- id: missing-cursor-hooks
  owner: Endpoint Security Team
  question: What was the specific model-assigned task that led to this command?
  remediation: Deploy the Elastic Agent hook script via MDM.
  requires: The log-tool-calls.sh script to be active on the host
  risk: Without local hook telemetry, we see the 'what' (shell command) but not the
    'why' (AI context), making it impossible to distinguish between developer steering
    and model hallucination.
  stage: agent-execution-environment-start
- id: cursor-restart-delay
  owner: IT Operations
  question: Are hosts showing 'green' on deployment actually collecting hooks?
  remediation: Prompt users to restart Cursor after the hook deployment script finishes.
  requires: A restart of the Cursor application after hook deployment
  risk: Cursor only reads hook configuration at startup; hosts that have not restarted
    will contribute no hook logs despite being 'compliant' in MDM.
  stage: agent-execution-environment-start
coverage:
- stage: agent-execution-environment-start
  status: covered
  steps:
  - cursor-agent-launches
- stage: automated-shell-execution
  status: covered
  steps:
  - rare-agent-shell-commands
- stage: agent-file-system-interaction
  status: covered
  steps:
  - sensitive-file-access
- stage: mcp-server-communication
  status: covered
  steps:
  - mcp-network-traffic
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: keep-as-periodic-hunt
  justification: AI agents with shell and file access introduce a new class of automated
    operator on the endpoint. A flight-recorder audit ensures we can reconstruct agent
    intent and actions after a model-steering or prompt-injection incident.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An AI agent operating under developer credentials is executing rare shell
  commands, accessing sensitive configuration files, or communicating with third-party
  MCP servers without explicit developer intent.
labels:
- hunt
- attack.t1059
- attack.t1059.001
- attack.t1090.003
name: AI Coding Agent Tool-Call Auditing
parameters:
  lookback_days:
    default: '14'
    description: Days of history to examine.
    type: number
  scope_hosts:
    default: []
    description: Specific hostnames to focus on; leave empty for all hosts.
    type: list[host]
  sensitive_extensions:
    default:
    - .pem
    - .key
    - .env
    - id_rsa
    - credentials
    - .git/config
    - .npmrc
    - .bash_history
    description: File names or extensions indicative of sensitive material.
    type: list[string]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://www.elastic.co/security-labs/blog/ai-coding-agent-audit-cursor-hooks
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Focus on developer laptops and engineering environments where AI coding
  agents are permitted. Start with a baseline of all hosts running Cursor in the last
  14 days.
references:
- name: "Elastic Security Labs \u2014 13 million tool calls: auditing every AI coding\
    \ agent action with Elastic Agent"
  url: https://www.elastic.co/security-labs/blog/ai-coding-agent-audit-cursor-hooks
related:
- hunt: claude-code-agent-auditing
  reason: Claude Code uses a similar agent-loop pattern but requires different hook
    registration.
  relation: sibling
scenario:
  stages:
  - name: AI Agent Session Initiation
    observables:
    - sessionStart
    - subagentStart
    - cursor_version
    - VSCODE_PID
    - cursor-agent
    slug: agent-execution-environment-start
    tactic: execution
    techniques:
    - T1059
  - name: AI Agent Shell Execution
    observables:
    - beforeShellExecution
    - afterShellExecution
    - 'command: npm test -- --watch=false'
    - 'command: curl'
    - 'tool_name: Shell'
    slug: automated-shell-execution
    tactic: execution
    techniques:
    - T1059
    - T1059.001
  - name: AI Agent File Read and Edit
    observables:
    - beforeReadFile
    - afterFileEdit
    - 'file_path: *.pem'
    slug: agent-file-system-interaction
    tactic: discovery
    techniques:
    - T1059
  - name: AI Agent MCP Tool Communication
    observables:
    - beforeMCPExecution
    - afterMCPExecution
    - mcp_server
    slug: mcp-server-communication
    tactic: command-and-control
    techniques:
    - T1090.003
  summary: AI coding agents like Cursor act as automated operators on developer endpoints,
    performing shell commands, file manipulations, and external API calls that are
    often indistinguishable from human activity. By leveraging agent lifecycle hooks
    and the Elastic Agent, defenders can record every tool call, shell command, and
    Model Context Protocol (MCP) request as structured events to audit automated actions
    and detect potential misuse or steering by malicious content.
severity: medium
targets:
  analyst:
    name: Tier-2 analyst
    role: analyst
  endpoint:
    category: endpoint
    name: Endpoint telemetry (hb_ surfaces)
    telemetry:
    - endpoint
  hunter:
    agent: true
    name: Hunt agent
  network:
    category: network
    name: Network telemetry
    telemetry:
    - network
tlp: clear
type: investigation
---


# AI Coding Agent Tool-Call Auditing

AI coding agents like Cursor act as automated operators on the endpoint, often masking their activity behind the developer's user context. This hunt implements a flight-recorder audit by first scoping the estate for Cursor installations and then examining the agent's behavior in phases. We baseline shell commands to find rare automated actions, identify sensitive file access patterns, and monitor for outbound MCP server connections that deviate from standard API traffic.

## find-cursor-installations
<!-- Scope Cursor installations -->
Identify hosts where Cursor or its headless agent is installed to define the hunt's scope.

```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hosts with the AI agent installed. Silence indicates no managed
  installations are visible.
reads:
- device_hostname
- package_name
silence: evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE LOWER(package_name) LIKE '%cursor%'
```

## parallel-early-activity
<!-- Analyze session and shell activity -->
parallel:
- → cursor-agent-launches
- → rare-agent-shell-commands
join: → early-stage-triage

## cursor-agent-launches
<!-- Cursor agent process launches -->
Detect the primary IDE and headless agent execution to establish session timelines.

```sqlite target=endpoint role=detection-candidate params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Process events for the Cursor binary. Frequent launches of the CLI agent
  may indicate automation or scripting.
reads:
- device_hostname
- process_name
- process_cmd_line
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_name, process_cmd_line, user_name, time FROM hb_process_activity WHERE (LOWER(process_name) LIKE '%cursor%' OR LOWER(process_name) LIKE '%cursor-agent%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## rare-agent-shell-commands
<!-- Rare agent-triggered shell commands -->
Stack-count shell commands spawned by Cursor to identify outliers. Includes the parent command line to provide context on the tool call that initiated the shell.

```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: Shell commands seen on very few hosts. This highlights rare scripts or network-interactive
  commands like curl.
prevalence:
  by: device_hostname
  key:
  - process_cmd_line
  rare_below: 3
reads:
- process_cmd_line
- parent_process_cmd_line
- device_hostname
- time
- parent_process_name
- process_name
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT process_cmd_line, parent_process_cmd_line, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_process_activity WHERE (LOWER(parent_process_name) LIKE '%cursor%' OR LOWER(parent_process_name) LIKE '%cursor-agent%') AND (LOWER(process_name) LIKE '%sh' OR LOWER(process_name) LIKE '%cmd.exe' OR LOWER(process_name) LIKE '%powershell%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_cmd_line, parent_process_cmd_line HAVING host_count <= 3 ORDER BY host_count ASC
```

## early-stage-triage
<!-- Early stage triage -->
```agent target=hunter
cite: required
context:
- cursor-agent-launches
- rare-agent-shell-commands
max_iterations: 3
objective: Determine if any Cursor processes have spawned shell commands that appear
  to be performing unauthorized discovery or exfiltration.
success_criteria: A per-host verdict of suspicious or benign, citing rare commands.
tools:
- endpoint
- network
```

## parallel-follow-on
<!-- Analyze file and network impact -->
parallel:
- → sensitive-file-access
- → mcp-network-traffic
join: → follow-on-triage

## sensitive-file-access
<!-- Sensitive file access by agent -->
Detect Cursor or its sub-processes reading sensitive configuration or credential files. Note: the current instr() logic performs an exact filename match against the list; it does not match partial extensions unless the full filename matches.

```sqlite target=endpoint role=enrichment params=(lookback_days=lookback_days, scope_hosts=scope_hosts, sensitive_extensions=sensitive_extensions)
~~~yaml
expected: File read events for credential-related filenames. Multiple hits on one
  host suggest an agent performing wide-scale credential discovery.
reads:
- device_hostname
- process_name
- parent_process_name
- file_path
- file_name
- time
silence: not_evidence_of_absence
source: hb_file_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_name, file_path, file_name, time FROM hb_file_activity WHERE (LOWER(process_name) LIKE '%cursor%' OR LOWER(parent_process_name) LIKE '%cursor%') AND instr(',' || '{{sensitive_extensions}}' || ',', ',' || LOWER(file_name) || ',') > 0 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## mcp-network-traffic
<!-- Agent network connections -->
Identify outbound connections from Cursor that represent potential MCP server communication. Hostname is used to identify high-fidelity third-party server indicators.

```sqlite target=network role=enrichment params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Connections to external IPs and hostnames. Connections to non-standard HTTP
  ports (e.g. 8080, 5000) may indicate third-party MCP servers.
reads:
- device_hostname
- process_name
- process_path
- dst_endpoint_hostname
- dst_endpoint_ip
- dst_endpoint_port
- direction
- time
silence: not_evidence_of_absence
source: hb_network_connection
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_name, dst_endpoint_hostname, dst_endpoint_ip, dst_endpoint_port, direction, time FROM hb_network_connection WHERE (LOWER(process_name) LIKE '%cursor%' OR LOWER(process_path) LIKE '%cursor%') AND direction = 'outbound' AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## follow-on-triage
<!-- Final agent triage -->
```agent target=hunter
cite: required
context:
- early-stage-triage
- sensitive-file-access
- mcp-network-traffic
max_iterations: 5
objective: Determine if the combination of rare shell commands, sensitive file access,
  and network traffic indicates a malicious model-steering event.
success_criteria: A verdict of malicious | suspicious | benign citing specific file
  paths and network destinations.
tools:
- endpoint
- network
```

## route-on-risk
<!-- Route on risk -->
if~: "the follow-on triage verdict is malicious for at least one host" (confidence: high, judge=hunter)
then: → isolate-endpoint
indeterminate: → forensic-review
unavailable: → forensic-review (blind_spot: missing-cursor-hooks)
else: → close-out-hunt

## isolate-endpoint
<!-- Isolate affected host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host and notify the user. Capture local Cursor hook logs if available.
```
→ forensic-review

## forensic-review
<!-- Forensic review of agent intent -->
```manual target=analyst
Review the project files (READMEs, .env, .config) on the affected host. Check if any remote MCP servers were specified in the Cursor configuration that are not company-standard.
```
→ close-out-hunt

## close-out-hunt
<!-- Close out hunt -->
```manual target=analyst
Record the findings. If rare but benign shell commands were found, add them to the fleet baseline to reduce future noise.
```
→ end

Run it

Take this hunt into your environment.

Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.

Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.