GenAI Agent Instruction File Written to Downloads

edit
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

GenAI Agent Instruction File Written to Downloads

edit

Detects creation or change of an AI coding-agent instruction file (agents.md or claude.md) in a user Downloads folder by a browser or an archive tool. A web page can save AGENTS.md or CLAUDE.md into Downloads without a click, and opening an archive can extract the same files there. Codex and Claude Code treat those files as trusted project instructions, which can lead them to rewrite their own configuration, install a package, or leak a login token.

Rule type: esql

Rule indices: None

Severity: medium

Risk score: 47

Runs every: 5m

Searches indices from: now-9m (Date Math format, see also Additional look-back time)

Maximum alerts per execution: 100

References:

Tags:

  • Domain: Endpoint
  • Domain: GenAI
  • Mitre Atlas: AML.T0051
  • Mitre Atlas: AML.T0093
  • OS: Linux
  • OS: Windows
  • OS: macOS
  • Use Case: Threat Detection
  • Tactic: Initial Access
  • Tactic: Execution
  • Data Source: Elastic Defend
  • Resources: Investigation Guide
  • Threat: Unauthorized AI Usage
  • Rule Type: ES|QL
  • Platform: Windows
  • Platform: Linux
  • Platform: macOS

Version: 1

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

Triage and analysis

Investigating GenAI Agent Instruction File Written to Downloads

AGENTS.md and CLAUDE.md are instruction files that coding agents such as OpenAI Codex and Claude Code read when a session starts in that folder and then follow. Downloads is a folder a browser can write to on its own, and it is also where archive tools extract files the user opened. A planted instruction file can tell the agent to register a malicious MCP server, install a package, or point its API traffic at an attacker-controlled gateway.

Possible investigation steps

  • Open file.path and read the file. Look for instructions that edit agent config (~/.codex/config.toml, .claude/settings.json, mcp.json), register an MCP server, run npx or npm install, or set ANTHROPIC_BASE_URL or a similar API base URL.
  • Review process.name and process.executable. A browser or browser helper means the file was saved from the web. An archive tool (7z, WinRAR, tar, unzip, Archive Utility) means it was extracted from a download.
  • On the same host and user, look for a preceding download of a zip, rar, or 7z into the same Downloads folder, and for follow-on writes to .codex, .claude, or other GenAI config paths.
  • Check whether Codex, Claude, or another agent was later started with that Downloads folder as its workspace, and whether it spawned npm, npx, node, or a shell afterward.
  • If the file is malicious, hunt the same filename and content hash on other hosts.

False positive analysis

  • Cloning or downloading a legitimate repository into Downloads extracts a real AGENTS.md or CLAUDE.md. Confirm the archive or URL and the file contents before excluding.
  • Saving those files from a browser while working on an agent project in Downloads is expected. Scope exceptions to a known path, user, or parent archive, not to the filename alone.

Response and remediation

  • Quarantine the instruction file and any archive it came from. Collect the hash and the download URL if present.
  • If an agent already consumed the file, review ~/.codex/config.toml, .claude/settings.json, and other MCP config for new servers or API base URLs, and remove unauthorized entries.
  • Rotate agent login tokens and any credentials the session could have read. Remove packages the agent installed as part of the instructions, such as an unexpected npm package.

Setup

edit

Setup

This rule is designed for data generated by Elastic Defend, which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.

Setup instructions: https://ela.st/install-elastic-defend

Rule query

edit
FROM logs-endpoint.events.file-* METADATA _id, _version, _index
| WHERE event.type IN ("creation", "change")
  AND TO_LOWER(file.name) IN ("agents.md", "claude.md")
  AND (
    file.path LIKE "/Users/*/Downloads/*"
    OR file.path LIKE "/home/*/Downloads/*"
    OR file.path LIKE """C:\\Users\\*\\Downloads\\*"""
  )
  AND (
    TO_LOWER(process.name) IN (
      "google chrome", "chrome.exe", "chrome", "chromium", "chromium-browser", "google-chrome",
      "microsoft edge", "msedge.exe", "microsoft-edge",
      "firefox", "firefox.exe",
      "safari",
      "brave browser", "brave.exe", "brave", "brave-browser",
      "opera", "opera.exe",
      "vivaldi", "vivaldi.exe",
      "explorer.exe",
      "com.apple.webkit.networking",
      "7z.exe", "7zg.exe", "7zfm.exe", "7z", "7zz",
      "winrar.exe", "rar.exe", "unrar.exe", "rar", "unrar",
      "winzip.exe", "winzip64.exe",
      "bandizip.exe", "peazip.exe",
      "tar.exe", "tar", "bsdtar",
      "unzip.exe", "unzip", "unar", "ditto",
      "archive utility", "bomarchivehelper",
      "the unarchiver", "keka",
      "file-roller", "ark"
    )
    OR TO_LOWER(process.name) LIKE (
      "google chrome helper*",
      "microsoft edge helper*",
      "brave browser helper*",
      "opera helper*",
      "vivaldi helper*"
    )
  )
| KEEP
    _id,
    _version,
    _index,
    data_stream.namespace,
    @timestamp,
    host.name,
    host.id,
    agent.id,
    user.name,
    user.domain,
    event.type,
    event.action,
    file.name,
    file.path,
    process.name,
    process.executable,
    process.entity_id

Framework: MITRE ATT&CKTM