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.
- Generated files. If the index is built from a CMS, a docs pipeline or an LLM, then whoever can write a page title or a description can write into the file. Sanitising at render time is the control.
- Third-party contribution. Partner listings, marketplace entries, community links. Anything a non-employee can add is content, not policy.
- Agents you run. If your own system ingests competitors' or suppliers' llms.txt files into a prompt, you are the consumer of untrusted instructions — with your own credentials in context.
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.
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