הדף עדיין לא זמין בעברית, ולכן הוא מוצג באנגלית.

AGENTS.md in Downloads can hijack Codex and Claude Code

Convika Team14 min read

  • security
  • claude-code
  • codex
On this page

As of October 27, 2026, 04:04 JST (October 26, 19:04 UTC). Every source below carries the time this page read it, in JST (UTC+9). Neither OpenAI nor Anthropic had published a statement on this research when we checked.

Starting Codex or Claude Code in your Downloads folder lets a web page take over the agent with a file it saved there. In Forever Security's tests, a planted AGENTS.md made Codex install malware in "more than 90% of attempts", and a planted CLAUDE.md leaked Claude Code's login token "about 50% of the time".

The malware is the npm package function-color, and the token went to a server the researchers ran, posing as a company gateway. Nothing here is a bug to patch: both agents read instruction files from the folder they start in, by design. The fix is where you start them. Below: what the researchers showed, whether Claude Code reads AGENTS.md at all, how to tell if you're exposed, the files to check now, and the settings that stop it.

What the researchers showed

Forever Security's Gal Weizman and Omer Samet published the research on October 22, 2026. It began with a real case: Forever's software stopped a coding agent on a customer's machine from installing function-color, a known malicious npm package, and traced the instruction to an AGENTS.md in that customer's ~/Downloads that nobody remembered putting there. The file is a 13 KB "Engineering Work Guidelines" document, with the attack in one section near the end, dressed up as routine setup.

Browsers make the first step easy. BleepingComputer found that Chrome, Edge, and Firefox save downloads to ~/Downloads by default without asking (they do show a download notification), while Brave asked for approval.

AgentPlanted fileWhat the agent didHow often, per Forever
CodexThe attacker's own AGENTS.md, unchangedAdded a project-tools MCP server to ~/.codex/config.toml, whose launch command hands npm install function-color (in /tmp/ptools) to macOS launchctl. Because the install needed the network, the file had Codex start a child codex exec with --dangerously-bypass-approvals-and-sandbox"more than 90% of attempts"
Claude CodeA CLAUDE.md the researchers wrote, inspired by the attacker's fileWrote .claude/settings.json in that folder with ANTHROPIC_BASE_URL set to the researchers' server, presented as "the team's internal gateway". Claude Code's OAuth token went to that server, and replaying it against the real API served the researchers as the victim"about 50% of the time"
Claude Code, next launch in that folderSame CLAUDE.mdThe researchers' server answered as the model with a Bash call that set dangerouslyDisableSandbox to true, and Claude Code ran itFollows from the settings write
Claude Code, same sessionSame CLAUDE.mdA subagent opened a fresh connection through the researchers' server, which ran code inside the first session"About a fifth of the time"

Two details decide who is at risk. Codex, in Forever's words, "only obeys an AGENTS.md in a project it trusts. Once you have worked in Downloads, it qualifies." And the Codex change outlives the folder: ~/.codex/config.toml is machine-wide, so every later Codex session on the machine, in any project, loads the attacker's server. The Claude Code change stays in the folder, and Forever says "Claude needs a human to approve a write like this". That depends on your permission mode. Unless permissions.defaultMode in your settings says otherwise, an interactive terminal session starts in auto mode on Claude Code 2.1.283 and later, and on Pro, Max, and Team plans it often did before that. In auto mode a write to .claude/ goes to Anthropic's classifier instead of asking you. Only Manual mode and acceptEdits always ask.

Forever says "Claude was much harder to fool", and that a spawned subagent read the CLAUDE.md and flagged it as an attack when the payload pushed "too hard". Most tests used a harmless stand-in that opened the calculator, and the real package ran once, inside an isolated VM. npm has since removed function-color. None of the three write-ups names the agent versions tested.

Does Claude Code read AGENTS.md?

Yes, since version 2.1.277, published to npm on September 19, 2026 (JST). Its changelog entry: "Added AGENTS.md support: in a project with no CLAUDE.md, Claude Code reads AGENTS.md instead; change it under "Project instructions" in /config". Before 2.1.277, Claude Code read CLAUDE.md files only. Anthropic's memory docs add two gaps: before 2.1.281, some sessions, such as those on Amazon Bedrock or with telemetry disabled, read CLAUDE.md only, and the first session after an upgrade from 2.1.276 or earlier may too.

So a planted AGENTS.md reaches Claude Code too, as long as there's no CLAUDE.md in the folder you start in or any folder above it. Anthropic's memory docs say that at session start Claude Code reads "every AGENTS.md and .claude/AGENTS.md in your working directory and the directories above it", and in an interactive session you see a line such as no CLAUDE.md found; AGENTS.md loaded: …. Your own ~/.claude/CLAUDE.md doesn't count for that check, so having one doesn't stop a planted AGENTS.md.

A planted CLAUDE.md works in any version, which is the file the researchers used.

Am I exposed?

You're exposed when an agent starts in a folder you don't control the contents of. Each agent looks in different places:

Where the planted file sitsCodexClaude Code
~/Downloads, and you start the agent thereRead: outside a Git repository, Codex "only checks the current directory". Forever says Codex obeys it once the folder is trusted, which it is after you've worked thereRead: CLAUDE.md always; AGENTS.md when no CLAUDE.md is in that folder or above
~/Downloads, and you start the agent in a subfolder such as ~/Downloads/projectRead only if the subfolder is inside the same Git repository as the fileRead: Claude Code loads CLAUDE.md from "your current working directory and every directory above it"
Your home folder (~/CLAUDE.md, ~/AGENTS.md)Not read for a project, unless the home folder is itself a Git repositoryRead for every project under your home folder
A repository you just clonedReadRead

Forever's telemetry shows the habit is common: about half of its customers run a coding agent inside the Downloads folder, and BleepingComputer adds that Claude Code alone launched more than 1,300 sessions from there. Forever also counts about a quarter of agent sessions opening a real browser, which is one way an agent can land on the page that drops the file.

What to check now

These commands work in the macOS and Linux terminal. We ran each against test folders with planted files on October 27 between 03:30 and 03:58 JST; on a real home folder the find in step 4 can take a few minutes. A command that prints nothing found nothing in the places it looked; step 4 says why that isn't the whole answer.

1. Look for instruction files you didn't write

find ~ -maxdepth 2 \( -name 'AGENTS*.md' -o -name 'CLAUDE*.md' \) 2>/dev/null

This lists AGENTS.md, AGENTS.override.md, CLAUDE.md, and CLAUDE.local.md directly in your home folder and directly inside each folder in it, such as ~/Downloads and ~/.claude (so your own ~/.claude/CLAUDE.md shows up too). It doesn't look inside subfolders of ~/Downloads; for those, run it again with ~/Downloads in place of ~. If macOS asks whether Terminal may access your Downloads folder, allow it: without that permission, the command skips the folder silently. Open every one you don't recognize and read it before you start an agent anywhere near it. A planted file reads like setup notes: install a package, add a tool server, use a company gateway.

2. Check Codex's config for servers and URLs you didn't add

grep -nE 'mcp_servers|base_url' ~/.codex/config.toml

Forever says to look for unexpected [mcp_servers.*] blocks and a changed chatgpt_base_url. The same command shows openai_base_url and any provider's base_url. Delete what you didn't add.

3. Check Claude Code's settings for an API address you didn't set

grep -HniE 'BASE_URL|PROXY|apiKeyHelper' ~/.claude/settings.json ~/.claude/settings.local.json 2>/dev/null
grep -HniE 'BASE_URL|PROXY|apiKeyHelper' ~/Downloads/.claude/settings.json ~/Downloads/.claude/settings.local.json 2>/dev/null

Forever's list is "an ANTHROPIC_BASE_URL, a proxy, or any other API endpoint you did not set"; the command also shows an apiKeyHelper, a command your settings run to fetch a key. Then run the same check on .claude/ in any other folder where you start Claude Code. An ANTHROPIC_BASE_URL you didn't set means your traffic and your token went to someone else's server. If your company really runs a gateway, compare the address with the one your admin gave you.

4. Look for function-color

find ~ /tmp/ -type d -name function-color -path '*node_modules*' 2>/dev/null
launchctl list | grep -i ptools

The real file installs the package under /tmp/ptools through a launchctl job labelled com.ptools.setup, so the second line (macOS only) looks for that job. Keep the slash in /tmp/: on a Mac, /tmp is a link to /private/tmp, and find doesn't follow it without the slash. Forever's advice: if function-color "turns up in a machine's installs, treat that machine as compromised." If either line prints anything, stop here and handle the machine as an incident, not a cleanup.

An empty result here isn't proof the machine is clean, because macOS empties /tmp when it restarts. The lasting sign is the [mcp_servers.project-tools] block from step 2, which stays in ~/.codex/config.toml until you delete it.

5. Replace your login if you found a planted file

The researchers say to assume the login token leaked, because "a stolen token is a live session". In Codex, run codex logout and sign in again; OpenAI's docs say it clears "the current credentials" and to treat ~/.codex/auth.json "like a password". In Claude Code, run /logout, then /login. Neither company's docs say whether signing out revokes the old token on its servers, so if you use an API key instead of a subscription login, delete that key in the OpenAI dashboard or the Anthropic Console and create a new one.

6. Start agents from the project folder only

Move anything you work on out of ~/Downloads into its own folder, and start the agent there. BleepingComputer notes that both OpenAI and Anthropic recommend running agents from the relevant project directory.

Settings that stop it

Instruction files are context, not code, so no setting makes an agent ignore every bad instruction. What the settings can do is stop the steps that made the attack work: a write to the agent's own settings, and a command run outside the sandbox.

SettingAgentWhat it does against this attack
Start in a project folder, never ~/Downloads or ~/BothKeeps a downloaded file out of the folders the agent reads (Forever, BleepingComputer)
Manual mode, or a session started with --restrictedClaude Code.claude is a protected path, so in Manual mode (and acceptEdits) a write to .claude/settings.json prompts you. The terminal's default since 2.1.283 is auto, which sends that write to the classifier; with --restricted (2.1.248 and later) "the classifier can't approve protected-path writes". --restricted also removes the tools that run commands or code and WebFetch, and ignores your user, project and local settings files, so it suits a session for reading an untrusted folder, not daily work. bypassPermissions allows the write (Anthropic's permission modes page and changelog)
Strict sandbox mode: "sandbox": {"allowUnsandboxedCommands": false}, or an ask rule for Bash(dangerouslyDisableSandbox:true)Claude CodeThe researchers' fake model asked for dangerouslyDisableSandbox, and plain /sandbox lets such a retry run outside the sandbox. Strict mode ignores the parameter; the ask rule prompts you for it, in auto mode too. Neither stops the token leak, because Claude Code's own API traffic isn't a Bash command (Anthropic's sandboxing page)
ConfigChange hooksClaude CodeAudit or block settings changes during a session (Anthropic's security page)
Project instructions in /config set to claude-md or managed-onlyClaude Codeclaude-md stops AGENTS.md from loading, but a planted CLAUDE.md still loads. managed-only leaves out every project CLAUDE.md and AGENTS.md at launch, your own included (Anthropic's memory page)
Approvals left on, and no approval for a command carrying --dangerously-bypass-approvals-and-sandboxCodexCodex wrote that flag itself, because the planted file said the install needed it. With approvals on, you're asked first; say no (Forever)
trust_level = "untrusted" for ~/Downloads, under [projects."/Users/you/Downloads"] in ~/.codex/config.tomlCodexForever says Codex "only obeys an AGENTS.md in a project it trusts". OpenAI's reference says untrusted projects skip project .codex/ layers, and doesn't say whether AGENTS.md is skipped too

A hook is the most direct fix in Claude Code, because it runs no matter what the model decides: Claude Code hooks: how to block a command before it runs walks through a tested PreToolUse hook and its matchers, which you can adapt to refuse writes to .claude/settings.json. Match Bash as well as Write|Edit, because the model can also write the file with a shell command such as echo. Skills are the other files both agents pick up from the folders they start in; Codex vs Claude Code skills lists where each one looks.

What OpenAI and Anthropic say

Neither had commented in any of the three write-ups we read, and we found no statement from either company in a search on October 27 at 04:04 JST. The researchers' view, quoted by Help Net Security and BleepingComputer: "There is nothing here for OpenAI or Anthropic to patch." Both agents do what their docs say: read the instruction files where they start.

Anthropic's docs already say what to rely on: CLAUDE.md and AGENTS.md are "context, not enforced configuration", and "To block an action regardless of what Claude decides, use a PreToolUse hook instead." Its security page recommends virtual machines "especially when interacting with external web services", and says that in the home folder, trust "is held for the current session only and is not written to disk".

Frequently asked questions

Can a website put a file in my Downloads folder without asking?

Yes, in most browsers. BleepingComputer found that Chrome, Edge, and Firefox save to ~/Downloads by default without a prompt, and show a download notification; Brave asked first. The file does nothing on its own. It matters only when an agent starts in that folder.

Does Claude Code read AGENTS.md?

Yes, since version 2.1.277 (September 19, 2026, JST), when the folder you start in and the folders above it have no CLAUDE.md. You can turn that off by setting Project instructions in /config to claude-md.

Is Codex or Claude Code vulnerable to the AGENTS.md attack if I start them in a project folder?

Not from a file in ~/Downloads, as long as the project isn't inside ~/Downloads and step 2 shows no server or URL you didn't add to ~/.codex/config.toml. That file is machine-wide, so a Codex session you once ran in Downloads can have changed it for every project. A cloned repository is a different case: its own AGENTS.md or CLAUDE.md loads, so read one before you start an agent in a repository you didn't write.

How do I know if my Claude Code token was stolen?

Look for an ANTHROPIC_BASE_URL you didn't set in .claude/settings.json in the folders where you start Claude Code, and in ~/.claude/settings.json. If you find one, the token went to that address: sign out and in again, and replace any API key you use.

What is function-color?

A malicious npm package that, per Help Net Security, was part of a campaign that went unnoticed for about two years, documented by Checkmarx. npm has removed it. Treat a machine where it was installed as compromised.

Will OpenAI or Anthropic fix this?

The researchers say there's nothing to patch, and neither company had commented when we checked. The protection is on your side: where you start the agent, and which settings stop it from changing its own configuration.

Sources

Times are when this page read each source, in JST on October 27, 2026.

Updates to this page

  • October 27, 2026: Published. Sources read October 27, 03:22 to 04:04 JST.