Chapter 36

The Documentation Was the Payload

An attacker registered a malicious npm package on the exact name Clerk's llms.txt told AI agents to install. It sat live in the npm registry for over a month.

✓ Verified Primary sources: OSV.dev record MAL-2026-11069; the llms.txt specification (Answer.AI, September 2024); npm v11 documentation; Liu et al., arXiv:2605.14460; Novee Security Black Hat 2026 disclosure (CVE-2026-54316); Cloud Security Alliance CISO Daily Briefing, 7 September 2026. Scan statistics are attributed to Compendia Labs and have not been independently replicated.
Share X LinkedIn Reddit HN
Key Facts
  • Malicious npm package MAL-2026-11069 (clerk-next-fix-auth-protection) published July 24, 2026 — CWE-506, exfiltrated user data via HTTP, flagged by OpenSSF Package Analysis and Amazon Inspector
  • Clerk's llms.txt file contained the command npx clerk-next-fix-auth-protection pointing at an unregistered package name; Clerk has since remediated
  • Liu et al. (Zhejiang University, May 2026) independently found AI agents treat documentation as "authoritative operational directives," with RCE success rates up to 67.33%
  • At Black Hat 2026, Novee Security demonstrated RCE in Claude Code Action, Gemini CLI, and Codex; Anthropic awarded three bug bounties and shipped fixes (CVE-2026-54316)
  • Cloud Security Alliance rated the llms.txt supply chain vector CRITICAL URGENCY (September 7, 2026), calling it "a genuinely new, cross-vendor class of supply chain exposure"

01 — ContextThe File That Became a Channel

On July 24, 2026, someone registered an npm package called clerk-next-fix-auth-protection. It contained install hooks that silently exfiltrated the user's hostname, username, and working directory over HTTP. The name was not random. It was the exact command that Clerk, an authentication platform used by thousands of developers, published in its llms.txt file for AI coding agents to run. Five weeks later, security researchers would give the vulnerability class a name.

To understand how a documentation file became a weapon, start with the file itself.

On September 3, 2024, Jeremy Howard — co-founder of Answer.AI and fast.ai — published a proposal for a new web convention: llms.txt. The idea was simple. Websites already publish robots.txt to tell crawlers what to index. Why not publish a plain-text file to help large language models answer questions about the site? The specification described a structured way to provide context — a company name, a description, links to key documentation pages. It was designed for chatbots assembling answers, not for agents executing commands. The specification contains zero security considerations. No trust model. No discussion of how an autonomous agent might act on the content. There was nothing to discuss: the use case was passive context retrieval.

Thousands of companies adopted it. Stripe, Clerk, Anthropic, Vercel, and hundreds of smaller vendors published llms.txt files. Then the context shifted. AI coding agents — Claude Code, OpenAI Codex, Gemini CLI — began reading llms.txt files not as reference material but as operational instructions. Researchers at Zhejiang University would later document the core mechanism: LLM coding agents treat documentation as "authoritative operational directives rather than passive documentation." An agent doesn't read a troubleshooting command as a suggestion. It reads it as something to execute.

The specification was not designed for this. But the agents did not consult the specification.

The danger crystallizes when a vendor's llms.txt contains an installation command — say, npx some-package — and no one owns some-package on the public npm registry. The npx command, bundled with npm, automatically fetches packages from the registry if they are not found locally and executes the package binary. If the name is unclaimed, anyone can register it. The agent will run whatever it finds. The command becomes a loaded gun with no trigger guard.

Clerk's llms.txt had exactly this problem. The file included a line directing agents to run:

clerk.com/llms.txt
# Clerk Documentation
 
> Clerk is an authentication and user management platform...
 
## Quickstart
...
 
## Troubleshooting
 
If you encounter auth protection issues with Next.js, run:
 
    npx clerk-next-fix-auth-protection
 
...

The command string is confirmed by multiple sources and corroborated by the existence of the malicious package at that exact name. Clerk had not published clerk-next-fix-auth-protection as a standalone npm package. The intended binary was bundled inside the scoped package @clerk/eslint-plugin. The bare name sat unclaimed on the public registry.

Until someone claimed it.

The Manifest — An acid-lime reader descends a column of identical dim lines, illuminating each and moving on; one line does not fade back — it holds its glow, opens a thin channel to the edge of the canvas, and a red pulse returns along it.

02 — What HappenedThe Package Nobody Published

On July 24, 2026, a third party — not Clerk, not the security researchers who would later publicize the vulnerability class — registered clerk-next-fix-auth-protection on npm. The package contained embedded malicious code, classified under CWE-506. Its install hooks harvested the user's hostname, username, and working directory and transmitted them via HTTP. The affected versions were numbered 7.7.7 and 8.8.8. OpenSSF Package Analysis detected the package. Amazon Inspector confirmed it. The vulnerability was cataloged as MAL-2026-11069.

MAL-2026-11069CWE-506
Packageclerk-next-fix-auth-protection
Ecosystemnpm
Versions7.7.7, 8.8.8
Published2026-07-24
Modified2026-08-04
Reported byOpenSSF Package Analysis
ConfirmedAmazon Inspector
ClassificationEmbedded Malicious Code
BehaviorExfiltrates username, hostname, working directory via HTTP during install

The timeline matters. MAL-2026-11069 was published on July 24, 2026 — over a month before the Compendia Labs blog post (August 29) that would bring public attention to the broader vulnerability class. The attacker found and exploited the gap independently. This was not a response to a researcher's disclosure. Someone looked at Clerk's llms.txt, saw an unclaimed package name referenced in an installation command, and registered a malicious package at that name.

Clerk acknowledged the issue and remediated it. The company stated that the expected binary was already present via @clerk/eslint-plugin, so there was no practical threat for existing users who had that package installed. As of September 9, 2026, Clerk's llms.txt files contain no reference to the command.

Clerk's defense deserves fair consideration. For developers who already had @clerk/eslint-plugin installed locally, npx would resolve the binary from the local installation and never reach the public registry. The malicious package would not execute. But this defense assumes the user — or the agent — had @clerk/eslint-plugin installed before running the command. A new developer setting up a project from scratch, a CI environment with a clean node_modules, an AI coding agent following documentation without any prior context — none of these would have the local package. In each case, npx would resolve the bare name against the public npm registry and execute whatever it found there. In this case, that was MAL-2026-11069.

There is an unresolved question at the center of this incident, and it deserves its own beat. When npx encounters a package it needs to fetch from the registry, it prints a confirmation prompt: "Need to install the following packages: ... Ok to proceed? (y)." This prompt can be suppressed with the --yes or -y flag. We do not know how AI coding agents handled this prompt. Did agents suppress it automatically with --yes? Did a human operator see the prompt and approve it? Did the prompt never appear for some other reason — a cached resolution, a configuration default? This is not a minor technical footnote. If agents suppressed the prompt, they bypassed a security checkpoint autonomously. If a human approved it, the human rubber-stamped the installation of an unknown package without examining it. If the prompt never appeared, the one safety mechanism in the chain failed silently. Each answer is damning differently, and none is established.

One more gap must be stated plainly. No public report confirms that an AI agent actually installed and executed MAL-2026-11069 specifically. The facts are: the malicious package existed at that exact name on npm; Clerk's documentation told agents to run that exact name; academic and industry research confirms that agents follow such instructions. The connection is logically direct. But no reported incident documents an agent completing the full chain — fetching the malicious package, executing the install hooks, exfiltrating user data. Honesty requires noting that we do not have proof one was fired.

03 — The MechanismWhy Agents Obey

The vulnerability class that the Clerk incident illustrates did not need Clerk to prove it existed. Two independent research efforts, with no connection to each other or to the researchers who later publicized the llms.txt attack surface, had already documented the core mechanism.

In May 2026, a team at Zhejiang University — Xinyu Liu, Yukai Zhao, Xing Hu, and Xin Xia — published a paper (arXiv:2605.14460) testing how LLM coding agents handle documentation. They tested three agent frameworks: OpenClaw, Claude Code, and Codex. Their finding was unambiguous. LLM coding agents "parse, trust, and act upon" natural language documentation "as authoritative operational directives rather than passive documentation." The agents did not treat skill descriptions as suggestions to evaluate. They treated them as instructions to execute. The paper reported remote code execution success rates ranging from 2.67% to 67.33% across model and framework combinations, with the stronger configurations clustering between 30.56% and 64.44%. The paper makes no reference to Compendia Labs, llms.txt, or the Clerk incident. It independently confirmed the fundamental mechanism: agents do what documentation tells them to do.

On August 6, 2026, at Black Hat 2026, Novee Security researcher Elad Meged presented a separate set of findings. Meged tested Claude Code Action (the GitHub Action integration), Gemini CLI, and OpenAI Codex and found exploitable remote code execution vulnerabilities in all three — triggered by what the presentation called "zero-privilege inputs," including content as mundane as a stranger's GitHub issue. The response from the vendors confirmed the severity. Anthropic awarded three bug bounties and shipped fixes. Google implemented what it described as "a breaking change to how non-interactive headless environments handle folder trust." OpenAI separated workflows and hardened its agent after a three-day disclosure window. A CVE was assigned: CVE-2026-54316. Novee Security's research has no connection to Compendia Labs. The finding is independent.

These two research efforts establish the vulnerability class on their own authority. Agents obey documentation. They execute commands embedded in text they are given to read. This is not a bug in a specific product. It is a property of how LLM-based coding agents process natural language instructions.

Attack Path — llms.txt to Code Execution
1
Vendor publishes llms.txt
"npx clerk-next-fix-auth-protection"
2
AI agent reads llms.txt
Treats documentation as directive
3
Agent runs: npx clerk-next-fix-auth-protection
Package not found locally
4
npx queries public npm registry
Finds clerk-next-fix-auth-protection (MAL-2026-11069)
5
Package installs and executes
Install hooks harvest hostname, username, cwd
6
Data exfiltrated via HTTP
Attacker receives machine fingerprint
This sequence is the logical path. No public report confirms that an agent completed steps 3–6 using the MAL-2026-11069 package specifically.

The Compendia Labs research adds scale context to this picture. According to a blog post published August 29, 2026, researchers affiliated with Compendia Labs scanned 6,214 live domains and resolved approximately 8,265 llms.txt files. They reported finding 120 files that referenced unregistered package names or domains, containing approximately 227 install commands pointing at unclaimed names. The researchers registered a subset of those names as inert beacon packages — phone-home telemetry only, no persistence, no data theft, no production damage, according to their account. They reported receiving callbacks from Fortune 500 networks within an hour. Process logs from the beacon packages, the researchers stated, identified the parent processes as Anthropic's Claude, OpenAI's Codex, and Nous Research's Hermes. Over subsequent days, they received what Bruce Schneier described as "a few dozen more" callbacks from corporate networks.

These numbers require a sourcing note the reader deserves to see plainly. The scan statistics originate from a single blog post on compendialabs.org, authored under the pseudonym "DK Dark Knight." The named researcher, Alon Hertz, does not appear on the Compendia Labs team page, which lists only "Hitesh" and "Tanya." Schneier described the group as "a stealth startup in Israel." The organization discloses no commercial products, funding, or revenue model. Multiple secondary outlets reported the findings before the blog post's publication date of August 29 — SOFX and Slashdot ran coverage on August 27 — and two different sets of numbers circulate in the coverage (8,265 versus 8,565 files; 227 versus 237 commands), both originating from the same research team. No independent party has replicated the scan. The scan statistics are useful for illustrating the potential scale of the problem, but they rest on a single partly pseudonymous, commercially opaque source.

The vulnerability class is confirmed regardless. Even without the Compendia Labs numbers, the independently established evidence is substantial: Liu et al. documented the mechanism in an academic paper. Novee Security demonstrated it at Black Hat, and three major vendors shipped patches in response. MAL-2026-11069 proves that someone already exploited it in the wild, on the exact name Clerk's documentation referenced. The Compendia Labs research adds a claim about breadth — how many llms.txt files contain similar landmines — but it is not load-bearing for the story's central finding.

3 Sep 2024
Jeremy Howard publishes llms.txt proposal (Answer.AI)
No security considerations in the specification.
May 2026
Liu et al. publish arXiv:2605.14460
Agents treat documentation as "authoritative operational directives." RCE success rates up to 67.33%.
24 Jul 2026
MAL-2026-11069 published to npm
clerk-next-fix-auth-protection registered by unknown third party. CWE-506. Exfiltrates hostname, username, cwd.
6 Aug 2026
Black Hat 2026 / Novee Security
Elad Meged presents RCE findings across Claude Code Action, Gemini CLI, Codex. CVE-2026-54316 assigned. Bug bounties awarded.
27 Aug 2026
First press coverage (SOFX, Slashdot)
Compendia Labs scan findings reported two days before the blog post.
29 Aug 2026
Compendia Labs blog post published
"The llms.txt Trust Model" by DK Dark Knight.
4 Sep 2026
Bruce Schneier amplifies
"Think Solar Winds-style supply chain attacks."
7 Sep 2026
Cloud Security Alliance CISO briefing
Rates finding CRITICAL URGENCY. "Genuinely new cross-vendor class."

04 — SignalThe Instruction Surface

On September 7, 2026, the Cloud Security Alliance rated the llms.txt supply chain exposure CRITICAL URGENCY in its CISO Daily Briefing. The CSA described it as "a genuinely new, cross-vendor class of supply chain exposure" — distinct from prior concerns about AI vendor concentration. The assessment's sharpest insight was about detection: according to the CSA, the attack "looks identical to sanctioned developer activity to conventional endpoint and network controls" — meaning it bypasses standard detection — because it flows through approved AI tools and trusted package managers. There is no malware signature. No anomalous network traffic. No unauthorized process. Just an agent doing exactly what it was told to do, by a file its vendor published, through a registry its organization trusts.

On September 4, 2026, Bruce Schneier wrote about the findings on his blog: "This kind of thing will be exploited. Think Solar Winds-style supply chain attacks." He added: "We cannot forget that AI coding agents are not yet trustworthy." Schneier provided no independent analysis beyond relaying the Compendia Labs research and drawing the SolarWinds comparison. But the comparison has weight. SolarWinds was a supply chain attack that succeeded precisely because the malicious code traveled through a trusted update channel. The llms.txt vector operates on the same principle: the payload arrives through the documentation the organization itself publishes, executed by the tools the organization itself approved.

The AI Files publishes an auto-generated llms.txt at /llms.txt — this story is about a convention this site itself uses. No agent vendor — Anthropic, OpenAI, or Nous Research — had responded to press inquiries about llms.txt-specific mitigations as of September 4, 2026, according to Schneier. The Black Hat 2026 findings show all three vendors have patched other RCE vectors (CVE-2026-54316, trust model changes, workflow separation), but no llms.txt-specific fix has been announced. The llms.txt specification, updated to v2 in August 2026, still contains no security model.

The structural problem extends beyond llms.txt. The convention was one of the first designed to make websites legible to AI agents. It will not be the last. API references, README files, onboarding guides, integration docs — any text that an AI agent reads is a potential instruction surface if the agent treats text as directive. Liu et al. demonstrated that this is precisely what agents do. The question is not whether llms.txt can be patched. llms.txt is a plain-text file. The question is what happens when every documentation site, every API reference, every troubleshooting page is a potential execution channel for autonomous agents, and no security model exists for any of them.

The internet now has a growing layer of machine-readable instruction files designed for AI agents. The security model for those files is the same one that existed before they were written — which is to say, none. When agents cannot distinguish a vendor's documentation from an attacker's trap — because the trap is the documentation, published at the name the vendor told the agent to trust — the security boundary does not move. It disappears.

What If?

The documented attack path — a single unregistered package name in a single vendor's llms.txt — was a manual, artisanal exploit. Someone looked at one file, found one unclaimed name, registered one malicious package. Now scale it. llms.txt files are public, crawlable, and machine-readable; that is their entire purpose. An attacker does not need to hunt for unregistered package names by hand — they can scan for them programmatically, exactly as the Compendia Labs researchers did. The researchers reported approximately 227 install commands pointing at unclaimed names across 120 corporate llms.txt files, and every one of those names is registrable on a public package registry for free. npm has no ownership verification for new package names. Neither does PyPI. So a single operator, in one afternoon, could register every unclaimed package name across every llms.txt file in the Fortune 500. Not one trap. All of them. Simultaneously. Each with a different second-stage payload tuned to the target's stack — dependency confusion for the fintech, credential harvesting for the defense contractor, a cryptominer for the startup that nobody audits. The installations flow through trusted tools from trusted registries. The process tree shows an approved coding agent executing a command from an approved vendor's documentation. Endpoint detection flags nothing. Network monitoring sees standard HTTPS to npmjs.com. In the CSA's own words, the attack "looks identical to sanctioned developer activity" — there is no signature to write, no indicator of compromise to hunt, no anomaly to detect, because from the security stack's perspective nothing anomalous occurred. The existing correction infrastructure — OSV.dev, npm audit, OpenSSF Scorecard — was built to catch malicious packages after they are published, not to prevent attacks that arrive through trusted documentation before the package even exists. MAL-2026-11069 sat in the npm registry for over a month before it was flagged. Multiply that by 227. How many get caught on day one? How many get caught at all? When the victims are maintaining their own attack surface — publishing machine-readable files that point agents at names nobody owns — and the attacker's code enters through the same door as the vendor's code, what exactly is left to defend?

How did this land?

Sources

← Previous Chapter 35 Generated Using Draft One 7 min read Next → Chapter 37 Desks, Badges, and Company Laptops 8 min read
New chapters · No spam
Get the next story in your inbox