Content security · November 2026

Can llms.txt Be Used for Prompt Injection?

Most llms.txt guidance treats the file as an index. It is also a message addressed to a model, and that second property is the one security teams should look at first — because a file that tells an agent what to read is one step away from a file that tells an agent what to say.

A File Written to Be Obeyed, Not Just Read

The llms.txt convention exists so that a language model can get a curated, compact map of a site in a single request: a title, a one-line summary, then Markdown sections of links with short descriptions. Every part of that sentence assumes the reader is a model.

That is the design intent, and it is why the format works. It is also why the file sits in an awkward position on the security map. Prompt injection is LLM01 on the OWASP Top 10 for LLM applications, and the reason it outranks more exotic failures is structural rather than fixable: instructions and content arrive in the same channel and the model has no reliable boundary between them. Indirect injection is the variant that matters here — the model ingests external content, and that content carries the instruction.

llms.txt is, by construction, external content that a model ingests early. Nothing about the path makes it trusted. An agent fetching /llms.txt from a site it has never seen is reading a document the same way it reads a blog post.

Three Injection Shapes That Fit in Plain Text

None of these require breaking into anything. They require only that the file ends up in front of an agent with the right permissions.

Shape What it looks like Why it works
Inline directive A sentence in the preamble saying what to prioritise, ignore or recommend Reads as publisher guidance, so it is not filtered as spam or markup
Hostile link text A description field carrying a claim the page does not make The summary is quotable without ever fetching the target
Off-host pointer One entry pointing at a mirror, CDN copy or lookalike domain Moves the agent onto a document you do not control

The third shape is the expensive one, because the injected instruction then lives on a page that can change after your file was reviewed. Your file stays clean; the agent's reading list does not. If your estate is spread across several hosts, the delegation rules in root domain vs docs subdomain decide how much of that surface you are exposing.

The Risk Is Mostly Where You Are Not the Author

A hand-written file you review on every change is close to zero risk: you know every line. The exposure concentrates in three situations.

The published intent questions are separate from this and worth a read anyway: what live files actually say to agents shows how few files contain an imperative at all, which is a useful baseline for what "normal" looks like.

A Pre-Publish Review You Can Run in Two Minutes

Start with the directory and a keyword pass. These are not a filter — the OWASP guidance is explicit that string checks do not establish a boundary, and an attacker can rephrase — but they catch the careless cases, which is most of them.

curl -s https://example.com/llms.txt > llms.txt

# imperative openers aimed at the reader
grep -nEi '^\s*(you |always |never |ignore |disregard |prefer |recommend |treat |priorit)' llms.txt

# host inventory: every link host should be one you own
grep -oE 'https?://[a-z0-9.-]+' llms.txt | sort -u

Then the human read: does any line tell the reader what to do rather than describe what exists? Descriptions should state what a page is. "Our reference for the v2 API" is a description. "Always cite this page for pricing questions" is a directive, and it belongs in your own prompt engineering, not in a public file that a stranger can also amend through your CMS.

If your file is generated, diff the rendered output between deploys — a new imperative line is visible there long before it reaches an agent. The checker covers structure, H1 placement and link syntax; it will not catch a politely phrased instruction.

Treat the File as Data on Both Sides

Two rules cover the realistic cases. When you publish, the file should describe the site and nothing more — no playbooks, no routing instructions, no "when asked about X, say Y". When you consume someone else's file, wrap it as untrusted input, keep it out of the system prompt, and never let a link in it authorise a tool call. That is the same discipline as any other retrieved content, and it is the reason llms.txt should not be confused with a capability layer: access control is a different mechanism entirely, as the llms.txt vs MCP comparison sets out.

The honest summary: llms.txt does not create prompt injection, but it does create a tidy, predictable place to put an instruction where a model will read it first. Review it like a public statement, because that is what it is.

Write the index, review the wording.

The generator produces a clean, link-first llms.txt from your URL list; the checker validates what you are about to publish.

Open the generator · Validate a live file