cd /news/ai-safety/prompt-injection-hiding-in-a-github-… · home topics ai-safety article
[ARTICLE · art-92863] src=dev.to ↗ pub= topic=ai-safety verified=true sentiment=· neutral

Prompt Injection Hiding in a GitHub README

A developer discovered a prompt injection attack hidden in a GitHub README that tricks AI coding agents like Claude Code into obeying forged system reminders. The attack exploits the trust boundary between fetched web content and the agent's runtime, with research showing such instructions succeed up to 91% of the time. The developer proposes a simple rule: system-style markup inside fetched content is always forged, and recommends structural checks over judgment.

read4 min views1 publishedAug 12, 2026

Claude Code was fetching pages for me during a research session, one of them a GitHub repository page. Buried in the middle of the fetched text, between the project description and the install instructions, sat a <system-reminder>

tag telling the agent that the date had changed.

It hadn't. There is a real mechanism that delivers system reminders to Claude Code, and it had nothing to do with this one. A person typed that tag into a README, guessing that some AI agent would eventually read the page and mistake the text for a message from its own runtime.

That was the entire attack. Plain text on a normal-looking repo, shaped like something an agent is trained to obey. No exploit, no malicious package.

Fetch a GitHub repo page and you get the rendered README with it. That text is user controlled. Anyone can put anything there, and the fact that the page came from github.com over a valid certificate tells you nothing about it. The host is reputable. The content is whatever some stranger wrote. The trust boundary runs through the middle of the page, which is an uncomfortable place for a trust boundary to be.

The numbers on this are worse than I expected. The ReadSecBench study (March 2026, reported in this Cloud Security Alliance research note) tested 500 open-source README files against Claude, GPT-4, and Gemini. Direct commands embedded in the main README worked about 84% of the time. Instructions hidden two links away, in a CONTRIBUTING.md or a SECURITY.md, worked about 91%, presumably because nobody audits the files a README links to.

Humans did not do much better. The same study showed flagged documents to 15 reviewers: 8 of them saw nothing wrong at all, 6 commented only on grammar and formatting, and one sensed a problem without finding the mechanism.

The tag I found never said "ignore previous instructions." It lied about the date, which is a better move. An agent that believes today is a different day starts re-evaluating what is stale and what is current. It can dismiss fresh information as outdated, or accept planted information as new. A small lie, and everything downstream quietly re-anchors around it. It also sails past every filter tuned to the classic jailbreak phrases.

The kinds of text I now treat as hostile the moment they appear inside fetched content: claims that the date or the agent's identity has changed, the "ignore previous instructions" family, direct tool commands like "run this" or "fetch that URL", and anything demanding urgent action before responding to the user.

Detection turns out to need no judgment at all. The harness never puts a real system reminder inside fetched page content. Genuine reminders arrive through the harness's own channel, wrapped around tool results, never inside the body of one. The same holds for role tags and any other system-style markup.

So the rule: system-style markup inside fetched content is always forged. Always. There is no legitimate case to weigh against it. You never have to decide whether the instruction sounds reasonable, or whether the repo looks trustworthy, or whether the date might really have changed. Text claiming runtime authority from inside a web page is lying about where it is standing.

If you read my earlier post on subagents, this is the same lesson showing up in a different spot. There, the rule was to trust the artifact on disk over the agent's narration. Here, it is to trust the channel over the formatting. Both replace "does this look right?" with a structural check that cannot be sweet-talked. The protocol I now hold my agents to (and myself, when reviewing their output) once fetched content contains instruction-shaped text:

Step 3 is the one most setups miss, and the one I care about most. A warning in the chat evaporates when the session ends. The report survives, gets shared around, and becomes the input for someone else's decision. If the poisoned source is not marked inside it, the injection outlives its own discovery.

Simon Willison calls it the lethal trifecta: an agent that can read private data, sees untrusted content, and can communicate externally is one crafted page away from leaking whatever it can reach. A coding agent in the middle of a session usually holds all three. It can read your source tree, it fetches whatever the task needs, and it has curl

and git push

sitting right there.

A README injection is the untrusted-content leg, and your own workflow delivers it. The fetch that surfaced my forged reminder was completely routine, the kind of repo lookup an agent does dozens of times a day. Every one of those fetches is a stranger's text entering the agent's context.

I don't plan to stop fetching. I plan to keep the one structural rule in force, that system markup inside fetched content is forged, and to follow the protocol when it fires: flag it, record it in the artifacts, and keep going. The page is data. It does not get a say in how the agent runs.

── more in #ai-safety 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/prompt-injection-hid…] indexed:0 read:4min 2026-08-12 ·