13 million tool calls: auditing every AI coding agent action with Elastic Agent
AI coding agents like Cursor execute shell commands, edit files, and call MCP servers under developer accounts, making their automated actions indistinguishable from human activity to EDR tooling. Elastic Security Labs built a hook-based audit pipeline using a bash script that records every agent tool call as JSONL, which Elastic Agent ships to Elasticsearch. Over 13 million tool-call events from 1,100+ machines reveal that file reads dominate agent activity and that ES|QL queries can hunt for credential file access, download-and-execute patterns, and MCP server inventory across the fleet.
Detection / Hunteropenrouter
What Happened
AI coding assistants like Cursor can automatically run shell commands, edit files, and call external tools on developer laptops. Security monitoring tools cannot tell whether a command was typed by a person or generated by an AI, which creates a gap in visibility during security investigations. Elastic built a logging system that records every action an AI coding agent takes, collecting over 13 million events from more than 1,100 machines since May. Organizations using AI coding agents should consider implementing similar audit logging to maintain visibility into automated actions on their endpoints, and should ensure developers understand what is being collected and why.
Key Takeaways
- AI coding agents with shell access create an EDR blind spot because all actions execute under the developer's account in developer-launched processes, making automated and human actions indistinguishable.
- A 280-line dependency-free bash script registered as a Cursor hook records every agent tool call as structured JSONL, shipped to Elasticsearch via Elastic Agent filestream integration.
- File reads dominate agent activity by approximately 4:1 over shell execution, contradicting the assumption that agents primarily run commands.
- Over 300 distinct MCP servers were discovered in use across the fleet, with 86% used by only one or two people, highlighting governance concerns around third-party tool access.
- The pipeline logs metadata only (command lines, file paths, tool names) and excludes file contents, prompts, and model responses to preserve developer privacy.
Affected Systems
- macOS workstations running Cursor IDE or cursor-agent CLI
- Linux workstations running Cursor IDE or cursor-agent CLI
- Windows workstations running Cursor IDE or cursor-agent CLI
Vulnerabilities (CVEs)
None identified.
Attack Chain
- Visibility Gap: AI coding agent runs shell commands, edits files, and calls MCP servers under the developer's account, making automated actions indistinguishable from human activity to EDR
- Collection: A bash script registered as a Cursor hook fires on every tool-call lifecycle event (session start/end, shell execution, file read/edit, MCP calls, sub-agent spawn) and writes structured JSONL logs locally
- Shipping: Elastic Agent filestream integration reads the JSONL logs and ships them to Elasticsearch with decode_json_fields processing into a logs-ai_hooks-* data stream
- Hunting: ES|QL queries across the data stream identify credential file access, download-and-execute patterns, MCP server inventory, and per-host agent activity
- Governance: Field-level security restricts access to ai_hooks.* fields; only metadata is collected, not file contents or model prompts
Detection Availability
- YARA Rules: No
- Sigma Rules: No
- Snort/Suricata Rules: No
- KQL Queries: No
- Splunk SPL Queries: No
- EQL Queries: No
- Other Detection Logic: Yes
- Platforms: ES|QL, Elastic Agent filestream integration
The article provides multiple ES|QL queries for hunting across AI agent activity, including credential file access detection, download-and-execute pattern matching, MCP server inventory, and per-host shell command auditing. A Custom Logs filestream integration configuration for Elastic Agent is also included. The collector script and deployment artifacts are available in the elastic/elasticsearch-labs GitHub repository.
Detection Engineering Assessment
| Dimension | Rating | Rationale |
|---|---|---|
| EDR Visibility | Low | EDR sees the same processes and commands whether initiated by a human or an AI agent. The article explicitly states that agent activity is indistinguishable from developer activity to EDR because it happens under the developer's account inside developer-launched processes. |
| Network Visibility | None | The article does not discuss network-level detection. The hook-based approach captures tool calls at the agent layer, not the network layer. |
| Detection Difficulty | Moderate | Deploying the hook script and Elastic Agent integration is straightforward, but requires coordination with MDM tooling, a Cursor restart on each endpoint, and ongoing maintenance as agent vendors change hook payloads. Coverage is bounded by the hook events the vendor exposes and does not extend to personal Cursor logins. |
Required Log Sources
- Cursor hooks.json configuration deployment
- JSONL hook logs from ~/.config/ai-hooks/logs/
- Elastic Agent filestream integration (logs-ai_hooks-* data stream)
- osquery for agent inventory and Shadow AI detection
Hunting Hypotheses
| Hypothesis | Telemetry | ATT&CK Stage | FP Risk |
|---|---|---|---|
| Consider hunting for AI agent sessions that read credential files such as .pem, .env, or files named credentials at a volume significantly above the established baseline for that host, as this may indicate a prompt-injected agent performing reconnaissance outside its expected working directory. | Elasticsearch logs-ai_hooks-* data stream with promoted file_path and hook_event_name fields | Collection (T1552.001) | High — agents routinely read .env files for connection settings; the value is in establishing a per-host baseline and investigating deviations from it. |
| Consider hunting for shell commands executed by AI agents that pipe curl output into sh or bash, which would indicate a download-and-execute pattern consistent with T1105. | Elasticsearch logs-ai_hooks-* data stream with beforeShellExecution events containing command field matching curl piped to shell | Execution (T1105) | Medium — some legitimate development workflows pipe curl to shell, but these should be rare and reviewable. |
| Consider hunting for hosts where Cursor is installed (per osquery inventory) but no hook events arrive, as this may indicate tampering with the hook configuration or script by a developer with admin rights. | osquery Shadow AI detection packs cross-referenced with logs-ai_hooks-* event presence per host | Defense Evasion | Low — a host with Cursor installed but zero hook events over an extended period is a strong signal of tampering or misconfiguration. |
| Consider hunting for MCP servers used by only one or two people across the fleet, as each MCP server is a third party with tool-level access to developer conversations and may warrant governance review. | Elasticsearch logs-ai_hooks-* data stream with mcp_server field aggregated by distinct user count | Discovery / Governance | Low for security; high for operational noise — the long tail of niche MCP servers is expected but each represents a third-party trust decision. |
Control Gaps
- EDR cannot distinguish AI agent-initiated actions from developer-initiated actions because both occur under the same account and process tree.
- Hook-based auditing does not capture prompts, model reasoning, or file contents, so intent behind actions is not visible.
- Cloud Distribution-pushed hooks only reach enterprise tenant accounts; personal Cursor logins are invisible to the pipeline.
- A developer with admin rights can remove hooks or edit the collector script; the system is tamper-evident at fleet level but not tamper-proof on a single host.
Key Behavioral Indicators
- beforeShellExecution hook events with command field containing curl piped to sh or bash
- beforeReadFile events with file_path matching *.pem, *.env, or credentials file patterns at volumes above per-host baseline
- Absence of hook events from hosts where Cursor is inventoried via osquery
- postToolUseFailure events indicating hook misbehavior after agent updates
- subagentStart events showing agent spawning sub-agents, which may indicate complex or chained tool usage
False Positive Assessment
High — AI coding agents routinely read .env files, run shell commands, and call MCP servers as part of normal development workflows. The article notes that file reads dominate by 4:1 over shell execution and that agents read .env files constantly. Detection value comes from establishing baselines and investigating deviations rather than alerting on individual events.
Recommendations
Immediate Mitigation
- Verify against your organization's incident response runbook and team escalation paths before acting. Consider deploying the hook collector script to a pilot group of developer endpoints to establish baseline visibility into AI coding agent activity.
- Consider inventorying which developer endpoints have Cursor or other AI coding agents installed, using osquery or equivalent endpoint inventory tooling, to understand the scope of the visibility gap.
- If your organization uses Elastic Agent, consider adding the Custom Logs filestream integration pointed at the hook log glob to begin centralized collection.
Infrastructure Hardening
- Consider deploying the hooks.json configuration system-wide via MDM to ensure all Cursor installations are covered, and budget for a Cursor restart prompt in the deployment plan since hooks are only read at startup.
- Evaluate whether field-level security or equivalent access controls can restrict who can query agent audit logs, treating them as sensitive per-person telemetry similar to DNS logs.
- If applicable, consider using Cloud Distribution to push hook configurations to machines not covered by MDM, such as Linux workstations enrolled in an enterprise Cursor tenant.
User Protection
- Consider publishing an internal page describing exactly what the hook pipeline collects, who can query it, and why, before fleet-wide deployment, to maintain trust with engineering teams.
- Evaluate whether the collector script's privacy-preserving design (logging metadata only, excluding file contents, prompts, and model responses) aligns with your organization's data handling policies.
- Consider setting local log file permissions to owner-only (chmod 0600) and implementing short local retention (e.g., 30 days) with the SIEM as the system of record.
Security Awareness
- Consider rolling into existing security awareness programs a note that AI coding agents can execute commands automatically and that their actions are now audited, so developers understand the visibility scope.
- If applicable, consider training security analysts on ES|QL or equivalent query languages to hunt across agent activity data, focusing on credential file access and download-and-execute patterns.
- Consider establishing a baseline of normal agent activity per host (e.g., typical daily file reads, shell commands) so that anomalous spikes can be identified during investigations.
MITRE ATT&CK Mapping
Execution
Credential Access
Command and Control
Additional IOCs
- File Paths:
/usr/local/share/ai-hooks/log-tool-calls.sh- Deployment path for the hook collector script on macOS and Linux. Cursor splits hook command paths on spaces, so the script must not live under a path containing spaces./Library/Application Support/Cursor/hooks.json- System-wide Cursor hooks configuration file on macOS. Both the IDE and CLI read this file at startup.~/.config/ai-hooks/logs/tool-calls-*.jsonl- Date-rotated JSONL log files written by the collector script. Permissions are set to 0600 (owner-only) and files older than 30 days are deleted locally.
- Command Lines:
- Purpose: Verify cursor-agent CLI hook coverage by running a test prompt and checking the latest log entry | Tools:
cursor-agent,tail| Stage: Validation |cursor-agent --print - Purpose: Self-installing hook command that carries the collector script gzipped and base64-encoded, pinned to a SHA-256 hash, for machines without MDM coverage | Tools:
bash,base64,gzip,sha256sum| Stage: Deployment
- Purpose: Verify cursor-agent CLI hook coverage by running a test prompt and checking the latest log entry | Tools:
- file_path~/.config/ai-hooks/logs/tool-calls-*.jsonlDate-rotated JSONL log files written by the collector script. Permissions are set to 0600 (owner-only) and files older than 30 days are deleted locally.
- file_path/Library/ApplicationSupport/Cursor/hooks.jsonSystem-wide Cursor hooks configuration file on macOS. Both the IDE and CLI read this file at startup.
- file_path/usr/local/share/ai-hooks/log-tool-calls.shDeployment path for the hook collector script on macOS and Linux. Cursor splits hook command paths on spaces, so the script must not live under a path containing spaces.