A security team registered package names that major companies had published in documentation built for AI agents. Four minutes later, one of those packages ran inside a Fortune 500 company. A second corporate callback arrived within the hour. Dozens followed.[1]
The researchers had found 8,565 llms.txt files across 6,214 live domains. Those files contained more than 237 install targets that nobody controlled: empty names on PyPI, npm, RubyGems, NuGet, crates.io, and Packagist, plus expired domains and abandoned cloud subdomains. The team claimed a small sample, published inert phone-home packages, and waited for the documentation to route agents into them.[1]
Claude, OpenAI Codex, and Hermes appeared in the recorded parent-process chains, according to Ars Technica. Endpoint security accepted the activity as ordinary developer work: an approved agent launched a familiar package manager against a registry already allowed through the network.[2]
The web added an instruction layer
llms.txt began as a proposal for giving language models a concise map of a website. A file at /llms.txt uses Markdown to describe the site and link to cleaner, machine-readable resources. The format helps an agent find a vendor’s API reference without chewing through navigation, ads, scripts, and thousands of irrelevant pages.[3]
Adoption moved quickly. OpenAI, Anthropic, and Google publish files for their developer documentation. Mintlify, GitBook, Wix, Yoast, and other platforms generate them. Chrome’s Lighthouse now includes an agentic-browsing audit that tells site owners where to place the file and how to structure it.[3][4]
That deployment story treated the format as better documentation plumbing. Coding agents gave it execution semantics. An agent asked to build against a vendor SDK can discover the vendor’s llms.txt, follow its links, read an installation line, and run the command. In the researchers’ test, a one-sentence request naming a vendor was enough. Across five frontier configurations and two agentic command-line tools, agents found the instruction channel without being given its URL.[1]
The resulting trust path crosses systems that prove different things. TLS authenticates a web origin. The documentation file establishes what the vendor appears to recommend. A public package registry resolves a name to whoever claimed it first. The agent collapses those separate facts into one conclusion: this command came from the vendor, so this package must belong to the vendor.
That conclusion has no cryptographic support.
The empty name is the payload route
This weakness resembles dependency confusion, but the instruction source is different. Classic dependency confusion exploits a build system that prefers a public package bearing the same name as an internal dependency. Here, public documentation supplies the exact name and the agent chooses to install it. The attacker can arrive months after the line was written. A typo, obsolete example, renamed package, expired domain, or hallucinated setup command leaves behind a slot anyone can claim.
No malicious text has to enter the document. The installation instruction can remain benign and first-party. Ownership changes elsewhere, at the registry or domain registrar, and the meaning of the old line changes with it.
The study found a live version of that failure in Clerk’s agent-facing documentation. The docs referenced npx clerk-next-fix-auth-protection. Clerk intended that command to invoke a binary shipped inside its scoped @clerk/eslint-plugin package. When the scoped package was absent locally, npx searched the public registry for a standalone package using the binary’s bare name. A third party had claimed that name and published malware whose install hooks transmitted the username, machine name, working directory, and timestamp to an external server.[1]
Google’s OSV catalog and Amazon Inspector classified the package as malicious under MAL-2026-11069 and CWE-506. Clerk responded to disclosure and corrected the documentation. The researchers said their own packages contained only inert callbacks, caused no persistence, and exfiltrated no data.[1]
Security started watching too late
Package registries, network proxies, and endpoint tools observe the final steps. By then, the decisive error has happened. The agent converted a statement found in content into authority to execute. The registry returned a valid package. The network saw an approved domain. The endpoint saw pip, npm, or npx launched by software the company intentionally installed.
Blocking every package manager would cripple the workflow companies bought agents to automate. Asking for a human click before every command creates approval theater when the reviewer receives the same authoritative-looking vendor page. A useful control has to preserve the distinctions the agent erased.
Package ownership should bind to documentation ownership. A vendor file that recommends pip install acme-client needs evidence that the vendor controls acme-client, or a policy that denies execution until ownership is verified. Install targets should be pinned where the ecosystem supports it, scanned at publication time, and scanned again because registries and domains change after docs ship. Bare npx commands deserve extra suspicion because lookup and execution can happen in one move without adding a dependency to the project manifest.
Agents also need a provenance boundary between reading and acting. Retrieved content can propose a command. A separate policy layer should decide whether that command may cross into execution using origin, package ownership, version, signature, destination, and workspace scope. The model should never be able to edit or waive that policy through more persuasive prose.
This changes the maintenance burden for every public technical document. A stale link used to waste a reader’s time. A stale install target can now transfer execution to a stranger. Documentation inventories need the same retirement discipline applied to DNS, package namespaces, signing keys, and CI credentials. Generated llms-full.txt files make the problem nastier by copying old examples into a high-trust surface that few humans review directly.
The standard itself has no execution requirement. Its proposal says agents should use the file to find relevant material. Chrome’s audit checks whether the file exists and follows the expected structure; it does not establish integrity for every package or domain the file names.[3][4] The dangerous behavior appears in the harness, where browsing, interpretation, shell access, and credentials meet.
That distinction matters because blaming a text file produces a cosmetic fix. Removing llms.txt leaves README files, issue threads, API references, tickets, emails, and retrieved web pages available to the same agent. Every readable surface can carry an instruction. The format made the trust path easy to measure. The harness gives the path force.
For agent builders, the research lands as an operational test rather than a philosophical warning. Put an unclaimed package name in trusted-looking documentation, ask the agent to integrate the vendor, and watch whether it verifies ownership before execution. If the answer depends on the model feeling cautious that day, the control does not exist.
The web spent decades separating content from active code with browser sandboxes, permissions, origin rules, and content security policy. Coding agents reconnect the two through natural language, then carry the result into a shell. That bridge needs an explicit security architecture. Right now, a Markdown line on an official domain can inherit the authority of a package maintainer, a developer, and an endpoint operator at once.
Sources
[1] https://medium.com/@alonhertz1/data-became-code-we-ran-code-inside-fortune-500s-using-files-they-published-for-ai-agents-0cd67ffbbffc | Alon Hertz, Data Became Code [2] https://arstechnica.com/security/2026/08/claude-codex-and-hermes-installed-unowned-code-inside-corporate-networks | Ars Technica, Claude, Codex, and Hermes installed unowned code inside corporate networks [3] https://llmstxt.org/ | The llms.txt v2 proposal [4] https://developer.chrome.com/docs/lighthouse/agentic-browsing/llms-txt | Chrome Lighthouse llms.txt audit